コード例 #1
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _print_cyclic_core(x, y, xcore, ycore, essential, t0, prm, fol):
    """Print results of cyclic core computation.

    Assert support and covering properties.
    """
    if log.getEffectiveLevel() > logging.INFO:
        return
    # assert
    if essential != fol.false:
        assert support_issubset(essential, prm.p_vars, fol)
    if xcore != fol.false:
        assert support_issubset(xcore, prm.p_vars, fol)
    if ycore != fol.false:
        assert support_issubset(ycore, prm.p_vars, fol)
    # print
    m = fol.count(x)
    n = fol.count(y)
    log.info(('(x={m}, y={n}) implicants of '
              'covering problem').format(m=humanize.intcomma(m),
                                         n=humanize.intcomma(n)))
    m = fol.count(xcore)
    n = fol.count(ycore)
    log.info(('(x={m}, y={n}) implicants after '
              'removing essential elements').format(m=humanize.intcomma(m),
                                                    n=humanize.intcomma(n)))
    n = fol.count(essential)
    log.info('{n} primes are essential'.format(n=humanize.intcomma(n)))
    t1 = time.time()
    dt = t1 - t0
    log.info('cyclic core took {dt}'.format(dt=humanize.naturaldelta(dt)))
コード例 #2
0
ファイル: cover.py プロジェクト: johnyf/omega
def _maxima(u, bab, fol):
    """Return maximal elements of `u` wrt `bab.p_leq_q`.

    @param u: function of `bab.p_vars`
    """
    assert support_issubset(u, bab.p_vars, fol)
    v = fol.let(bab.p_to_q, u)
    #
    r = v & bab.p_leq_q
    r = ~ r | bab.p_eq_q
    r = fol.forall(bab.q_vars, r)
    r &= u
    '''
    q = ', '.join(bab.q_vars)
    s = (
        '{u} /\ '
        '\A {q}:  ({v} /\ {p_leq_q}) => ({p_eq_q})').format(
            u=u,
            v=v,
            p_leq_q=bab.p_leq_q,
            p_eq_q=bab.p_eq_q,
            q=q)
    r = fol.add_expr(s)
    '''
    assert support_issubset(r, bab.p_vars, fol)
    return r
コード例 #3
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _cyclic_core_fixpoint(x, y, bab, fol):
    """Return cyclic core and essential elements."""
    log.debug('\n\n---- cyclic core fixpoint ----')
    assert x in fol.bdd, x
    assert y in fol.bdd, y
    assert support_issubset(x, bab.p_vars, fol)
    assert support_issubset(y, bab.p_vars, fol)
    # compute
    essential = fol.false
    xold, yold = None, None
    i = 0
    while x != xold or y != yold:
        log.debug('starting iteration {i}'.format(i=i))
        t0 = time.time()
        xold, yold = x, y
        x = _max_transpose(x, y, bab, fol, signatures=True)
        e = x & y
        x = x & ~e
        y = y & ~e
        essential |= e
        y = _max_transpose(x, y, bab, fol)
        t1 = time.time()
        dt = t1 - t0
        log.debug('iteration {i} took {dt:1.2f} sec'.format(i=i, dt=dt))
        i += 1
    _assert_fixpoint(x, y, xold, yold, essential, bab.p_vars, fol)
    log.debug('==== cyclic core fixpoint ====\n')
    return x, y, essential
コード例 #4
0
ファイル: cover.py プロジェクト: johnyf/omega
def _cyclic_core_fixpoint(x, y, bab, fol):
    """Return cyclic core and essential elements."""
    log.debug('\n\n---- cyclic core fixpoint ----')
    assert x in fol.bdd, x
    assert y in fol.bdd, y
    assert support_issubset(x, bab.p_vars, fol)
    assert support_issubset(y, bab.p_vars, fol)
    # compute
    essential = fol.false
    xold, yold = None, None
    i = 0
    while x != xold or y != yold:
        log.debug('starting iteration {i}'.format(i=i))
        t0 = time.time()
        xold, yold = x, y
        x = _max_transpose(x, y, bab, fol, signatures=True)
        e = x & y
        x = x & ~ e
        y = y & ~ e
        essential |= e
        y = _max_transpose(x, y, bab, fol)
        t1 = time.time()
        dt = t1 - t0
        log.debug('iteration {i} took {dt:1.2f} sec'.format(
            i=i, dt=dt))
        i += 1
    _assert_fixpoint(
        x, y, xold, yold, essential, bab.p_vars, fol)
    log.debug('==== cyclic core fixpoint ====\n')
    return x, y, essential
コード例 #5
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _maxima(u, bab, fol):
    """Return maximal elements of `u` wrt `bab.p_leq_q`.

    @param u: function of `bab.p_vars`
    """
    assert support_issubset(u, bab.p_vars, fol)
    v = fol.let(bab.p_to_q, u)
    #
    r = v & bab.p_leq_q
    r = ~r | bab.p_eq_q
    r = fol.forall(bab.q_vars, r)
    r &= u
    '''
    q = ', '.join(bab.q_vars)
    s = (
        '{u} /\ '
        '\A {q}:  ({v} /\ {p_leq_q}) => ({p_eq_q})').format(
            u=u,
            v=v,
            p_leq_q=bab.p_leq_q,
            p_eq_q=bab.p_eq_q,
            q=q)
    r = fol.add_expr(s)
    '''
    assert support_issubset(r, bab.p_vars, fol)
    return r
コード例 #6
0
def _cyclic_core_fixpoint_recursive(x, y, path_cost, bab, fol):
    """Return all minimal covers of `x` made with elements from `y`."""
    log.info('\n\n---- cyclic core ----')
    assert x in fol.bdd, x
    assert y in fol.bdd, y
    assert support_issubset(x, bab.p_vars, fol)
    assert support_issubset(y, bab.p_vars, fol)
    xold, yold = x, y
    # assert `x` refines `y`
    yq = fol.let(bab.p_to_q, y)
    assert cov._cover_refines(x, yq, bab.p_leq_q, bab.p_vars, bab.q_vars, fol)
    # max ceilings and max floors
    xt = cov._max_transpose(xold, yold, bab, fol, signatures=True)
    yt = cov._max_transpose(xt, yold, bab, fol)
    # Note: This order of computation is different than
    # in the function `cover._cyclic_core_fixpoint`.
    y_floors = cov._floor(xt, yold, bab, fol, signatures=False)
    e = xt & yt  # essential elements
    x = xt & ~e
    y = yt & ~e
    # path_cost + cost(essential)
    new_path_cost = path_cost + cov._cost(e, bab.prm, fol)
    if (x == xold and y == yold) or (x == fol.false):
        mincovers_core = _traverse_exhaustive(x, y, new_path_cost, bab, fol)
    else:
        mincovers_core = _cyclic_core_fixpoint_recursive(
            x, y, new_path_cost, bab, fol)
    if not mincovers_core:
        return set()
    assert mincovers_core
    assert (fol.count(e) > 0) or (fol.count(y) > 0)
    # add essential elements
    r = set(mincovers_core)
    mincovers_core = set()
    for cover in r:
        assert y_floors | ~cover == fol.true
        cover |= e
        assert fol.count(cover) > 0
        mincovers_core.add(cover)
    # enumerate all minimal covers
    assert y_floors | ~yt == fol.true
    assert y_floors | ~e == fol.true
    _assert_are_covers(xt, mincovers_core, bab, fol)
    _assert_covers_from(mincovers_core, yt, fol)
    _assert_uniform_cardinality(mincovers_core, fol)
    mincovers_floor = _mincovers_from_floor(mincovers_core, xt, y_floors, bab,
                                            fol)
    assert mincovers_floor
    _assert_are_covers(xt, mincovers_floor, bab, fol)
    _assert_covers_from(mincovers_floor, y_floors, fol)
    _assert_uniform_cardinality(mincovers_floor, fol)
    mincovers = _mincovers_from_unfloor(mincovers_floor, yold, bab, fol)
    assert mincovers
    _assert_are_covers(xold, mincovers, bab, fol)
    _assert_covers_from(mincovers, yold, fol)
    _assert_uniform_cardinality(mincovers, fol)
    log.info('==== cyclic core ====\n')
    return mincovers
コード例 #7
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _concretize_implicants(implicants_p, prm, fol):
    """Return covered set as function of `x`."""
    assert support_issubset(implicants_p, prm.p_vars, fol)
    # concretize
    x_in_p = lat.x_in_implicant(prm, fol)
    u = x_in_p & implicants_p
    covered_x = fol.exist(prm.p_vars, u)
    assert support_issubset(covered_x, prm.x_vars, fol)
    return covered_x
コード例 #8
0
def _assert_are_covers(x, covers, prm, fol):
    """Assert that each element of `covers` covers `x`."""
    assert support_issubset(x, prm.p_vars, fol)
    for cover in covers:
        assert support_issubset(cover, prm.p_vars, fol)
        yq = fol.let(prm.p_to_q, cover)
        assert support_issubset(yq, prm.q_vars, fol)
        assert cov._cover_refines(x, yq, prm.p_leq_q, prm.p_vars, prm.q_vars,
                                  fol)
コード例 #9
0
ファイル: cover.py プロジェクト: johnyf/omega
def _concretize_implicants(implicants_p, prm, fol):
    """Return covered set as function of `x`."""
    assert support_issubset(implicants_p, prm.p_vars, fol)
    # concretize
    x_in_p = lat.x_in_implicant(prm, fol)
    u = x_in_p & implicants_p
    covered_x = fol.exist(prm.p_vars, u)
    assert support_issubset(covered_x, prm.x_vars, fol)
    return covered_x
コード例 #10
0
def _y_unfloor(yfloor, y, prm, fol):
    """Compute the elements from `y` that are above `yfloor`."""
    assert support_issubset(yfloor, prm.p_vars, fol)
    d = fol.pick(yfloor)
    assert set(d) == prm.p_vars, d
    yq = fol.let(prm.p_to_q, y)  # y(q)
    p_leq_y = prm.p_leq_q & yq  # Leq[z(p), y(q)]
    y_over_q = fol.let(d, p_leq_y)  # ThoseOver(y, yfloor)(q)
    y_over = fol.let(prm.q_to_p, y_over_q)  # ThoseOver(y, yfloor)(p)
    assert support_issubset(y_over, prm.p_vars, fol)
    assert y_over != fol.false
    return y_over
コード例 #11
0
ファイル: cover.py プロジェクト: ciniks117/omega
def _floor(p_is_signature, p_is_prime,
           bab, fol, signatures=False):
    """Transpose primes (tau_X(Y)) or signatures (tau_Y(X)).

    Floor(S) = Join(S)
    Ceil(S) = Meet(S)

    @param p_is_prime: some primes, function of `p`
    @param p_is_signature: function of `p`
    @param signatures: if `True`, then transpose signatures,
        otherwise primes.
    """
    log.info('---- tranpose ----')
    p_leq_u = bab.p_leq_u
    u_leq_p = bab.u_leq_p
    if signatures:
        p_is_signature, p_is_prime = p_is_prime, p_is_signature
        u_leq_p, p_leq_u = p_leq_u, u_leq_p
    # assert
    assert support_issubset(p_is_prime, bab.p_vars, fol)
    assert support_issubset(p_is_signature, bab.p_vars, fol)
    # p' used as u
    u_is_signature = fol.let(bab.p_to_u, p_is_signature)
    # same coverage
    p_like_q = _contains_covered(
        u_is_signature, u_leq_p, bab, fol)
    u_like_q = fol.let(bab.p_to_u, p_like_q)
    # u_is_prime = fol.let(p_to_u, p_is_prime)
    q_is_prime = fol.let(bab.p_to_q, p_is_prime)
    #
    r = ~ u_like_q | p_leq_u
    r = fol.forall(bab.u_vars, r)
    r &= p_like_q
    r &= q_is_prime
    r = fol.exist(bab.q_vars, r)
    '''
    q = ', '.join(iter(p_to_q.values()))
    u = ', '.join(iter(p_to_u.values()))
    s = (
        '\E {q}:  {q_is_prime} /\ {p_like_q} /\ '
        '    \A {u}:  {u_like_q} => {p_leq_u}').format(
            q=q,
            u=u,
            q_is_prime=q_is_prime,
            p_like_q=p_like_q,
            u_like_q=u_like_q,
            p_leq_u=p_leq_u)
    r = fol.add_expr(s)
    '''
    assert support_issubset(r, bab.p_vars, fol)
    log.info('==== tranpose ====')
    return r
コード例 #12
0
ファイル: cover.py プロジェクト: johnyf/omega
def _floor(p_is_signature, p_is_prime,
           bab, fol, signatures=False):
    """Transpose primes (tau_X(Y)) or signatures (tau_Y(X)).

    Floor(S) = Join(S)
    Ceil(S) = Meet(S)

    @param p_is_prime: some primes, function of `p`
    @param p_is_signature: function of `p`
    @param signatures: if `True`, then transpose signatures,
        otherwise primes.
    """
    log.info('---- tranpose ----')
    p_leq_u = bab.p_leq_u
    u_leq_p = bab.u_leq_p
    if signatures:
        p_is_signature, p_is_prime = p_is_prime, p_is_signature
        u_leq_p, p_leq_u = p_leq_u, u_leq_p
    # assert
    assert support_issubset(p_is_prime, bab.p_vars, fol)
    assert support_issubset(p_is_signature, bab.p_vars, fol)
    # p' used as u
    u_is_signature = fol.let(bab.p_to_u, p_is_signature)
    # same coverage
    p_like_q = _contains_covered(
        u_is_signature, u_leq_p, bab, fol)
    u_like_q = fol.let(bab.p_to_u, p_like_q)
    # u_is_prime = fol.let(p_to_u, p_is_prime)
    q_is_prime = fol.let(bab.p_to_q, p_is_prime)
    #
    r = ~ u_like_q | p_leq_u
    r = fol.forall(bab.u_vars, r)
    r &= p_like_q
    r &= q_is_prime
    r = fol.exist(bab.q_vars, r)
    '''
    q = ', '.join(iter(p_to_q.values()))
    u = ', '.join(iter(p_to_u.values()))
    s = (
        '\E {q}:  {q_is_prime} /\ {p_like_q} /\ '
        '    \A {u}:  {u_like_q} => {p_leq_u}').format(
            q=q,
            u=u,
            q_is_prime=q_is_prime,
            p_like_q=p_like_q,
            u_like_q=u_like_q,
            p_leq_u=p_leq_u)
    r = fol.add_expr(s)
    '''
    assert support_issubset(r, bab.p_vars, fol)
    log.info('==== tranpose ====')
    return r
コード例 #13
0
ファイル: cover.py プロジェクト: johnyf/omega
def _assert_fixpoint(x, y, xold, yold, essential, pvars, fol):
    """Assert `x, y = xold, yold` and check supports."""
    assert x == xold
    assert y == yold
    e = x & y
    assert e == fol.false, e
    e = x & essential
    assert e == fol.false, e
    e = y & essential
    assert e == fol.false, e
    assert support_issubset(x, pvars, fol)
    assert support_issubset(y, pvars, fol)
    assert support_issubset(essential, pvars, fol)
コード例 #14
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _assert_fixpoint(x, y, xold, yold, essential, pvars, fol):
    """Assert `x, y = xold, yold` and check supports."""
    assert x == xold
    assert y == yold
    e = x & y
    assert e == fol.false, e
    e = x & essential
    assert e == fol.false, e
    e = y & essential
    assert e == fol.false, e
    assert support_issubset(x, pvars, fol)
    assert support_issubset(y, pvars, fol)
    assert support_issubset(essential, pvars, fol)
コード例 #15
0
def _branch_exhaustive(x, y, path_cost, bab, fol):
    log.info('\n\n---- branch ----')
    mincovers = set()
    assert support_issubset(x, bab.p_vars, fol)
    assert support_issubset(y, bab.p_vars, fol)
    d = fol.pick(y)
    assert set(d) == bab.p_vars, (d, bab.p_vars, fol.support(y))
    # must be specific implicant
    # This condition follows because Y is an antichain when we pick.
    log.info('picked branching y: {d}'.format(d=d))
    y_branch = fol.assign_from(d)
    ynew = y & ~y_branch
    assert ynew != y
    # r(p) == p <= y_branch
    dq = {bab.p_to_q[k]: v for k, v in d.items()}
    r = fol.let(dq, bab.p_leq_q)  # those x under y_branch
    x_minus_y = x & ~r
    assert x_minus_y != x  # must prove always the case
    log.info('left branch')
    mincovers_left = _cyclic_core_fixpoint_recursive(x_minus_y, ynew,
                                                     path_cost + 1, bab, fol)
    # add `y_branch` to `mincovers_left`
    r = set(mincovers_left)
    mincovers_left = set()
    for mincover in r:
        mincover |= y_branch
        mincovers_left.add(mincover)
    log.info('right branch')
    mincovers_right = _cyclic_core_fixpoint_recursive(x, ynew, path_cost, bab,
                                                      fol)
    if not mincovers_left:
        return mincovers_right
    if not mincovers_right:
        return mincovers_left
    # pick smaller covers, or
    # take union if of same cardinality
    assert mincovers_left, mincovers_left
    assert mincovers_right, mincovers_right
    e_left = next(iter(mincovers_left))
    e_right = next(iter(mincovers_right))
    cost_left = cov._cost(e_left, bab.prm, fol)
    cost_right = cov._cost(e_right, bab.prm, fol)
    if cost_left < cost_right:
        mincovers = mincovers_left
    elif cost_left > cost_right:
        mincovers = mincovers_right
    elif cost_left == cost_right:
        mincovers = mincovers_left
        mincovers.update(mincovers_right)
    log.info('==== branch ====\n')
    return mincovers
コード例 #16
0
ファイル: cover.py プロジェクト: ciniks117/omega
def _independent_set(
        x, y, p_leq_q, p_to_q, fol, only_size=False):
    """Return an independent set of implicants and its size.

    Requires that each implicant in `x` be covered
    by at least one implicant in `y`.

    @param only_size: Do not return the independent set.
        This avoids creating the BDD of a sparse set.
    """
    log.debug('---- independent set ----')
    p = set(p_to_q)
    q = set(p_to_q.values())
    assert support_issubset(x, p, fol), (fol.support(x), p)
    assert support_issubset(y, p, fol), (fol.support(y), p)
    yq = fol.let(p_to_q, y)
    assert _cover_refines(x, yq, p_leq_q, p, q, fol)
    rem = x
    z = fol.false
    k = 0
    n = fol.count(rem)
    assert n >= 0, n
    while rem != fol.false:
        x0 = fol.pick(rem)
        assert set(x0) == p, x0
        if not only_size:
            z |= fol.assign_from(x0)
        # umbrella of x0
        #
        # r(p) == \E q:  /\ x0 <= q
        #                /\ p <= q
        #                /\ y(q)
        r = yq & fol.let(x0, p_leq_q)
        r &= p_leq_q
        r = fol.exist(q, r)
        # update
        assert support_issubset(r, p, fol)
        rem &= ~ r
        k += 1
        # variant
        nold = n
        n = fol.count(rem)
        assert n < nold, (n, nold)
    assert fol.count(rem) == 0, 'some x not covered'
    _assert_possible_cover_size(k, x, fol)
    log.debug('==== independent set ====')
    if only_size:
        return None, k
    k_ = fol.count(z)
    assert k == k_, (k, k_)
    return z, k
コード例 #17
0
ファイル: cover.py プロジェクト: johnyf/omega
def _independent_set(
        x, y, p_leq_q, p_to_q, fol, only_size=False):
    """Return an independent set of implicants and its size.

    Requires that each implicant in `x` be covered
    by at least one implicant in `y`.

    @param only_size: Do not return the independent set.
        This avoids creating the BDD of a sparse set.
    """
    log.debug('---- independent set ----')
    p = set(p_to_q)
    q = set(p_to_q.values())
    assert support_issubset(x, p, fol), (fol.support(x), p)
    assert support_issubset(y, p, fol), (fol.support(y), p)
    yq = fol.let(p_to_q, y)
    assert _cover_refines(x, yq, p_leq_q, p, q, fol), r
    rem = x
    z = fol.false
    k = 0
    n = fol.count(rem)
    assert n >= 0, n
    while rem != fol.false:
        x0 = fol.pick(rem)
        assert set(x0) == p, x0
        if not only_size:
            z |= fol.assign_from(x0)
        # umbrella of x0
        #
        # r(p) == \E q:  /\ x0 <= q
        #                /\ p <= q
        #                /\ y(q)
        r = yq & fol.let(x0, p_leq_q)
        r &= p_leq_q
        r = fol.exist(q, r)
        # update
        assert support_issubset(r, p, fol)
        rem &= ~ r
        k += 1
        # variant
        nold = n
        n = fol.count(rem)
        assert n < nold, (n, nold)
    assert fol.count(rem) == 0, 'some x not covered'
    _assert_possible_cover_size(k, x, fol)
    log.debug('==== independent set ====')
    if only_size:
        return None, k
    k_ = fol.count(z)
    assert k == k_, (k, k_)
    return z, k
コード例 #18
0
ファイル: orthotopes.py プロジェクト: johnyf/omega
def prime_implicants(f, prm, fol):
    """Return dominators of implicants."""
    log.info('----- prime orthotopes ----')
    assert support_issubset(f, prm.x_vars, fol)
    p_is_implicant = _implicant_orthotopes(f, prm, fol)
    q_is_implicant = fol.let(prm.p_to_q, p_is_implicant)
    r = q_is_implicant & prm.p_leq_q
    r = prm.p_eq_q | ~ r
    r = fol.forall(prm.q_vars, r)
    r &= p_is_implicant
    '''
    q = ', '.join(prm.q_vars)
    s = (
        '{p_is_implicant} /\ '
        r'\A {q}:  ( '
        '     ({q_is_implicant} /\ {p_leq_q})'
        '     => {p_eq_q}'
        ')').format(
            p_is_implicant=p_is_implicant,
            q_is_implicant=q_is_implicant,
            p_leq_q=prm.p_leq_q,
            p_eq_q=prm.p_eq_q,
            q=prm.q_vars)
    r = fol.add_expr(s)
    '''
    log.info('==== prime orthotopes ====')
    return r
コード例 #19
0
ファイル: orthotopes.py プロジェクト: tichakornw/omega
def prime_implicants(f, prm, fol):
    """Return dominators of implicants."""
    log.info('----- prime orthotopes ----')
    assert support_issubset(f, prm.x_vars, fol)
    p_is_implicant = _implicant_orthotopes(f, prm, fol)
    q_is_implicant = fol.let(prm.p_to_q, p_is_implicant)
    r = q_is_implicant & prm.p_leq_q
    r = prm.p_eq_q | ~r
    r = fol.forall(prm.q_vars, r)
    r &= p_is_implicant
    '''
    q = ', '.join(prm.q_vars)
    s = (
        '{p_is_implicant} /\ '
        r'\A {q}:  ( '
        '     ({q_is_implicant} /\ {p_leq_q})'
        '     => {p_eq_q}'
        ')').format(
            p_is_implicant=p_is_implicant,
            q_is_implicant=q_is_implicant,
            p_leq_q=prm.p_leq_q,
            p_eq_q=prm.p_eq_q,
            q=prm.q_vars)
    r = fol.add_expr(s)
    '''
    log.info('==== prime orthotopes ====')
    return r
コード例 #20
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _some_cover(x, y, p_leq_q, p_to_q, fol, only_size=False):
    """Return a cover and its size, possibly not minimal.

    Signature similar to `_independent_set`.
    """
    log.debug('---- some cover ----')
    p = set(p_to_q)
    q = set(p_to_q.values())
    assert support_issubset(x, p, fol), (fol.support(x), p)
    assert support_issubset(y, p, fol), (fol.support(y), p)
    yq = fol.let(p_to_q, y)
    assert _cover_refines(x, yq, p_leq_q, p, q, fol), r
    rem = x
    z = fol.false
    k = 0
    n = fol.count(rem)
    assert n >= 0, n
    while rem != fol.false:
        x0 = fol.pick(rem)  # x0
        assert set(x0) == p, x0
        # ys that cover x0
        #
        # r(q) == /\ x0 <= q
        #         /\ y(q)
        r = yq & fol.let(x0, p_leq_q)
        y0 = fol.pick(r)
        assert set(y0) == q, y0
        if not only_size:
            z |= fol.assign_from(y0)
        # x that y0 does not cover
        # rem(p) /\ ~ (p <= y0)
        rem &= ~fol.let(y0, p_leq_q)
        k += 1
        # variant
        nold = n
        n = fol.count(rem)
        assert n < nold, (n, nold)
    assert fol.count(rem) == 0, 'some x not covered'
    _assert_possible_cover_size(k, x, fol)
    log.debug('==== some cover ====')
    if only_size:
        return None, k
    q_to_p = {v: k for k, v in p_to_q.items()}
    zp = fol.let(q_to_p, z)
    k_ = fol.count(z)
    assert k == k_, (k, k_)
    return zp, k
コード例 #21
0
ファイル: cover.py プロジェクト: johnyf/omega
def _some_cover(x, y, p_leq_q, p_to_q, fol, only_size=False):
    """Return a cover and its size, possibly not minimal.

    Signature similar to `_independent_set`.
    """
    log.debug('---- some cover ----')
    p = set(p_to_q)
    q = set(p_to_q.values())
    assert support_issubset(x, p, fol), (fol.support(x), p)
    assert support_issubset(y, p, fol), (fol.support(y), p)
    yq = fol.let(p_to_q, y)
    assert _cover_refines(x, yq, p_leq_q, p, q, fol), r
    rem = x
    z = fol.false
    k = 0
    n = fol.count(rem)
    assert n >= 0, n
    while rem != fol.false:
        x0 = fol.pick(rem)  # x0
        assert set(x0) == p, x0
        # ys that cover x0
        #
        # r(q) == /\ x0 <= q
        #         /\ y(q)
        r = yq & fol.let(x0, p_leq_q)
        y0 = fol.pick(r)
        assert set(y0) == q, y0
        if not only_size:
            z |= fol.assign_from(y0)
        # x that y0 does not cover
        # rem(p) /\ ~ (p <= y0)
        rem &= ~ fol.let(y0, p_leq_q)
        k += 1
        # variant
        nold = n
        n = fol.count(rem)
        assert n < nold, (n, nold)
    assert fol.count(rem) == 0, 'some x not covered'
    _assert_possible_cover_size(k, x, fol)
    log.debug('==== some cover ====')
    if only_size:
        return None, k
    q_to_p = {v: k for k, v in p_to_q.items()}
    zp = fol.let(q_to_p, z)
    k_ = fol.count(z)
    assert k == k_, (k, k_)
    return zp, k
コード例 #22
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _max_transpose(p_is_signature, p_is_prime, bab, fol, signatures=False):
    """Maximal transposed primes or signatures.

    (max tau_Y(X) or max tau_X(Y))

    @param signatures: if `True`, then transpose signatures,
        otherwise primes.

    Requires that `p, p', q` be in `fol.vars` and
    be refined by the same number of bits each.
    """
    log.info('---- max transpose ----')
    assert support_issubset(p_is_prime, bab.p_vars, fol)
    assert support_issubset(p_is_signature, bab.p_vars, fol)
    # compute
    u = _floor(p_is_signature, p_is_prime, bab, fol, signatures=signatures)
    r = _maxima(u, bab, fol)
    assert support_issubset(r, bab.p_vars, fol)
    log.info('==== max transpose ====')
    return r
コード例 #23
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _covers_naive(cover_p, f, prm, fol):
    """Return `True` if `cover_p` covers `f`.

    Same as `covers`. Here the computation happens over
    the concrete variables (`x`), so it is less efficient.
    """
    assert support_issubset(f, prm.x_vars, fol)
    # concretize
    x_in_cover = _concretize_implicants(cover_p, prm, fol)
    covered = ~f | x_in_cover
    return covered == fol.true
コード例 #24
0
ファイル: cover.py プロジェクト: johnyf/omega
def _covers_naive(cover_p, f, prm, fol):
    """Return `True` if `cover_p` covers `f`.

    Same as `covers`. Here the computation happens over
    the concrete variables (`x`), so it is less efficient.
    """
    assert support_issubset(f, prm.x_vars, fol)
    # concretize
    x_in_cover = _concretize_implicants(cover_p, prm, fol)
    covered = ~ f | x_in_cover
    return covered == fol.true
コード例 #25
0
def _make_table(u, aut, care_source=None, care_target=None, care_bits=None):
    """Return symbol table with primed vars and care relation.

    The variables in `a.vars` should be unprimed.
    """
    bdd = aut.bdd
    care_relation = _care_relation(care_source, care_target, aut.prime, bdd)
    t = symbolic._prime_and_order_table(aut.vars)
    if care_bits is not None:
        assert scope.support_issubset(u, care_bits, bdd), (support, care_bits)
    return t, care_relation
コード例 #26
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _no_duplicate(u_p, prm, fol):
    """Return `True` if no doubly parameterized implicant in `u_p`."""
    assert support_issubset(u_p, prm.p_vars, fol)
    # checks that parameterization restricted to `u` is injective
    # \A p, q \in u:  eq(p, q) => (p = q)
    u_q = fol.let(prm.p_to_q, u_p)
    eq_implicants = prm.p_eq_q
    eq_parameters = _equality_of_pairs(prm.p_to_q.items(), fol)
    bound = u_p & u_q
    r = ~bound | ~eq_implicants | eq_parameters
    r = fol.forall(prm.p_vars | prm.q_vars, r)
    return r == fol.true
コード例 #27
0
ファイル: cover.py プロジェクト: johnyf/omega
def _no_duplicate(u_p, prm, fol):
    """Return `True` if no doubly parameterized implicant in `u_p`."""
    assert support_issubset(u_p, prm.p_vars, fol)
    # checks that parameterization restricted to `u` is injective
    # \A p, q \in u:  eq(p, q) => (p = q)
    u_q = fol.let(prm.p_to_q, u_p)
    eq_implicants = prm.p_eq_q
    eq_parameters = _equality_of_pairs(prm.p_to_q.items(), fol)
    bound = u_p & u_q
    r = ~ bound | ~ eq_implicants | eq_parameters
    r = fol.forall(prm.p_vars | prm.q_vars, r)
    return r == fol.true
コード例 #28
0
ファイル: cover.py プロジェクト: johnyf/omega
def _lower_bound_naive(x, y, p_leq_q, p_to_q, fol):
    """Return lower bound.

    Naive computation that greedily constructs
    an independent set.
    """
    log.debug('---- naive lower bound ----')
    z, n = _independent_set(x, y, p_leq_q, p_to_q, fol)
    assert support_issubset(z, p_to_q, fol)
    _assert_possible_cover_size(n, x, fol)
    log.info('lower bound = {n}'.format(n=n))
    log.debug('==== naive lower bound ====')
    return n
コード例 #29
0
ファイル: cover.py プロジェクト: johnyf/omega
def _upper_bound_naive(x, y, p_leq_q, p_to_q, fol):
    """Return upper bound.

    Naive computation that greedily constructs
    an irredundant cover.
    """
    log.debug('---- naive upper bound ----')
    cover, n = _some_cover(x, y, p_leq_q, p_to_q, fol)
    assert support_issubset(cover, p_to_q, fol)
    _assert_possible_cover_size(n, x, fol)
    log.info('upper bound = {n}'.format(n=n))
    log.debug('==== naive upper bound ====')
    return n
コード例 #30
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _upper_bound_naive(x, y, p_leq_q, p_to_q, fol):
    """Return upper bound.

    Naive computation that greedily constructs
    an irredundant cover.
    """
    log.debug('---- naive upper bound ----')
    cover, n = _some_cover(x, y, p_leq_q, p_to_q, fol)
    assert support_issubset(cover, p_to_q, fol)
    _assert_possible_cover_size(n, x, fol)
    log.info('upper bound = {n}'.format(n=n))
    log.debug('==== naive upper bound ====')
    return n
コード例 #31
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _lower_bound_naive(x, y, p_leq_q, p_to_q, fol):
    """Return lower bound.

    Naive computation that greedily constructs
    an independent set.
    """
    log.debug('---- naive lower bound ----')
    z, n = _independent_set(x, y, p_leq_q, p_to_q, fol)
    assert support_issubset(z, p_to_q, fol)
    _assert_possible_cover_size(n, x, fol)
    log.info('lower bound = {n}'.format(n=n))
    log.debug('==== naive lower bound ====')
    return n
コード例 #32
0
ファイル: cover.py プロジェクト: johnyf/omega
def _contains_covered(u_is_signature, u_leq_p, bab, fol):
    """Return primes that cover all signatures under prime.

    CAUTION: keep `u_leq_p` in the arguments,
    because the function `_floor` swaps with `p_leq_u`
    before calling `_contains_covered`.

    In the proof, this operator is equivalent to:
        `IsAbove(p, ThoseUnder(u_is_signature, q, Leq))`

    @param signatures: function of `u`
    """
    log.info('---- contains covered ----')
    # assert
    pq_vars = bab.p_vars.union(bab.q_vars)
    pu_vars = bab.p_vars.union(bab.u_vars)
    assert support_issubset(u_is_signature, bab.u_vars, fol)
    assert support_issubset(u_leq_p, pu_vars, fol)
    # compute
    u_leq_q = fol.let(bab.p_to_q, u_leq_p)
    r = u_is_signature & u_leq_q
    r = ~ r | u_leq_p
    r = fol.forall(bab.u_vars, r)
    '''
    uvars = ', '.join(bab.u_vars)
    s = (
        '\A {uvars}:  '
        '    ({sig_u} /\ {u_leq_q}) '
        '        => {u_leq_p}').format(
        uvars=uvars,
        sig_u=u_is_signature,
        u_leq_q=u_leq_q,
        u_leq_p=u_leq_p)
    r = fol.add_expr(s)
    '''
    assert support_issubset(r, pq_vars, fol)
    log.info('==== contains covered ====')
    return r
コード例 #33
0
def _below_and_suff(ymax, cover, x, y, prm, fol):
    """Return subset of `y` that is below `ymax` and suffices.

    A `yk \in y` suffices if it covers all elements in `x`
    that are covered by `ymax` but not by any element of `y`
    other than `ymax`.
    """
    assert support_issubset(ymax, prm.p_vars, fol)
    assert support_issubset(cover, prm.p_vars, fol)
    assert support_issubset(x, prm.p_vars, fol)
    assert support_issubset(y, prm.p_vars, fol)
    assert ymax != fol.false
    assert (cover | ~ymax) == fol.true
    # `cover` is Q
    other_y = cover & ~ymax
    p_leq_q = prm.p_leq_q
    other_yq = fol.let(prm.p_to_q, other_y)
    u = x & p_leq_q & other_yq
    u = fol.exist(prm.q_vars, u)
    # x covered by only `ymax`, among those y in` cover`
    x_sig_ymax = x & ~u  # Only(ymax, cover)
    assert x_sig_ymax != fol.false
    # find the y above these x,
    # and below ymax
    assert (y | ~ymax) == fol.true
    yq = fol.let(prm.p_to_q, y)
    ymax_q = fol.let(prm.p_to_q, ymax)
    u = (p_leq_q & yq) | ~x_sig_ymax
    u = fol.forall(prm.p_vars, u)
    assert u != fol.false
    # Yonly == {y \in Y:  \A q \in Only(ymax, cover):  Leq[q, y]}
    y_only = fol.let(prm.q_to_p, u)
    u = y_only & p_leq_q & ymax_q
    # {y \in Yonly:  Leq[y, ymax]}
    yk_set = fol.exist(prm.q_vars, u)
    assert support_issubset(yk_set, prm.p_vars, fol)
    assert yk_set != fol.false
    return yk_set
コード例 #34
0
ファイル: cover.py プロジェクト: johnyf/omega
def _print_cyclic_core(
        x, y, xcore, ycore, essential,
        t0, prm, fol):
    """Print results of cyclic core computation.

    Assert support and covering properties.
    """
    if log.getEffectiveLevel() > logging.INFO:
        return
    # assert
    if essential != fol.false:
        assert support_issubset(essential, prm.p_vars, fol)
    if xcore != fol.false:
        assert support_issubset(xcore, prm.p_vars, fol)
    if ycore != fol.false:
        assert support_issubset(ycore, prm.p_vars, fol)
    # print
    m = fol.count(x)
    n = fol.count(y)
    log.info((
        '(x={m}, y={n}) implicants of '
        'covering problem').format(
            m=humanize.intcomma(m),
            n=humanize.intcomma(n)))
    m = fol.count(xcore)
    n = fol.count(ycore)
    log.info((
        '(x={m}, y={n}) implicants after '
        'removing essential elements').format(
            m=humanize.intcomma(m),
            n=humanize.intcomma(n)))
    n = fol.count(essential)
    log.info('{n} primes are essential'.format(
        n=humanize.intcomma(n)))
    t1 = time.time()
    dt = t1 - t0
    log.info('cyclic core took {dt}'.format(
        dt=humanize.naturaldelta(dt)))
コード例 #35
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _contains_covered(u_is_signature, u_leq_p, bab, fol):
    """Return primes that cover all signatures under prime.

    CAUTION: keep `u_leq_p` in the arguments,
    because the function `_floor` swaps with `p_leq_u`
    before calling `_contains_covered`.

    In the proof, this operator is equivalent to:
        `IsAbove(p, ThoseUnder(u_is_signature, q, Leq))`

    @param signatures: function of `u`
    """
    log.info('---- contains covered ----')
    # assert
    pq_vars = bab.p_vars.union(bab.q_vars)
    pu_vars = bab.p_vars.union(bab.u_vars)
    assert support_issubset(u_is_signature, bab.u_vars, fol)
    assert support_issubset(u_leq_p, pu_vars, fol)
    # compute
    u_leq_q = fol.let(bab.p_to_q, u_leq_p)
    r = u_is_signature & u_leq_q
    r = ~r | u_leq_p
    r = fol.forall(bab.u_vars, r)
    '''
    uvars = ', '.join(bab.u_vars)
    s = (
        '\A {uvars}:  '
        '    ({sig_u} /\ {u_leq_q}) '
        '        => {u_leq_p}').format(
        uvars=uvars,
        sig_u=u_is_signature,
        u_leq_q=u_leq_q,
        u_leq_p=u_leq_p)
    r = fol.add_expr(s)
    '''
    assert support_issubset(r, pq_vars, fol)
    log.info('==== contains covered ====')
    return r
コード例 #36
0
ファイル: orthotopes.py プロジェクト: johnyf/omega
def setup_lattice(prm, fol):
    """Store the lattice BDDs in `prm`."""
    log.info('partial order')
    u_leq_p, p_leq_u = partial_order(prm._px, fol)
    log.info('subseteq')
    p_leq_q = subseteq(prm._varmap, fol)
    log.info('eq')
    p_eq_q = eq(prm._varmap, fol)
    pq_vars = prm.p_vars.union(prm.q_vars)
    assert support_issubset(p_leq_q, pq_vars, fol)
    prm.u_leq_p = u_leq_p
    prm.p_leq_u = p_leq_u
    prm.p_leq_q = p_leq_q
    prm.p_eq_q = p_eq_q
コード例 #37
0
ファイル: cover.py プロジェクト: johnyf/omega
def _max_transpose(p_is_signature, p_is_prime,
                   bab, fol, signatures=False):
    """Maximal transposed primes or signatures.

    (max tau_Y(X) or max tau_X(Y))

    @param signatures: if `True`, then transpose signatures,
        otherwise primes.

    Requires that `p, p', q` be in `fol.vars` and
    be refined by the same number of bits each.
    """
    log.info('---- max transpose ----')
    assert support_issubset(p_is_prime, bab.p_vars, fol)
    assert support_issubset(p_is_signature, bab.p_vars, fol)
    # compute
    u = _floor(
        p_is_signature, p_is_prime,
        bab, fol, signatures=signatures)
    r = _maxima(u, bab, fol)
    assert support_issubset(r, bab.p_vars, fol)
    log.info('==== max transpose ====')
    return r
コード例 #38
0
ファイル: cover.py プロジェクト: johnyf/omega
def _cost(u, prm, fol):
    """Return numerical cost of cover `u`.

    ASSUME that no two assignments that satisfy `u`
    represent the same implicant (no duplicates).
    """
    if u is None:
        return float('inf')
    # cost of each implicant = 1
    # cost of a cover = number of implicants it contains
    assert _no_duplicate(u, prm, fol)
    assert support_issubset(u, prm.p_vars, fol)
    n = fol.count(u)
    return n
コード例 #39
0
ファイル: orthotopes.py プロジェクト: tichakornw/omega
def setup_lattice(prm, fol):
    """Store the lattice BDDs in `prm`."""
    log.info('partial order')
    u_leq_p, p_leq_u = partial_order(prm._px, fol)
    log.info('subseteq')
    p_leq_q = subseteq(prm._varmap, fol)
    log.info('eq')
    p_eq_q = eq(prm._varmap, fol)
    pq_vars = prm.p_vars.union(prm.q_vars)
    assert support_issubset(p_leq_q, pq_vars, fol)
    prm.u_leq_p = u_leq_p
    prm.p_leq_u = p_leq_u
    prm.p_leq_q = p_leq_q
    prm.p_eq_q = p_eq_q
コード例 #40
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _cost(u, prm, fol):
    """Return numerical cost of cover `u`.

    ASSUME that no two assignments that satisfy `u`
    represent the same implicant (no duplicates).
    """
    if u is None:
        return float('inf')
    # cost of each implicant = 1
    # cost of a cover = number of implicants it contains
    assert _no_duplicate(u, prm, fol)
    assert support_issubset(u, prm.p_vars, fol)
    n = fol.count(u)
    return n
コード例 #41
0
def print_nodes(u, dvars, bdd, care_set=None, care_bits=None):
    """Enumerate first-order models of a set.

    A set of nodes is defined over unprimed variables.

    @param dvars: table of unprimed variables
    @type bdd: `BDD`
    """
    assert scope.is_state_predicate(u), u.support
    if u == bdd.false:
        print('empty set')
        return
    if care_bits is not None:
        assert scope.support_issubset(u, care_bits, bdd), (support, care_bits)
    _print_enumeration(u, bdd, dvars, care_set, care_bits)
コード例 #42
0
ファイル: orthotopes.py プロジェクト: tichakornw/omega
def _implicant_orthotopes(f, prm, fol):
    """Return orthotopes that imply `f`.

    Caution: `fol` type hints are ignored.
    """
    log.info('---- implicant orthotopes ----')
    x_vars = prm.x_vars
    assert support_issubset(f, x_vars, fol)
    x = ', '.join(x_vars)
    h = x_in_implicant(prm, fol)
    nonempty = _orthotope_nonempty(prm._px, fol)
    s = ('{nonempty} /\ '
         '\A {x}:  {h} => {f} ').format(x=x, h=h, f=f, nonempty=nonempty)
    r = fol.add_expr(s)
    log.info('==== implicant orthotopes ====')
    return r
コード例 #43
0
ファイル: orthotopes.py プロジェクト: johnyf/omega
def _implicant_orthotopes(f, prm, fol):
    """Return orthotopes that imply `f`.

    Caution: `fol` type hints are ignored.
    """
    log.info('---- implicant orthotopes ----')
    x_vars = prm.x_vars
    assert support_issubset(f, x_vars, fol)
    x = ', '.join(x_vars)
    h = x_in_implicant(prm, fol)
    nonempty = _orthotope_nonempty(prm._px, fol)
    s = (
        '{nonempty} /\ '
        '\A {x}:  {h} => {f} ').format(
            x=x, h=h, f=f, nonempty=nonempty)
    r = fol.add_expr(s)
    log.info('==== implicant orthotopes ====')
    return r
コード例 #44
0
ファイル: symbolic_test.py プロジェクト: tichakornw/omega
def test_assert_support():
    fol = setup()
    u = fol.add_expr('x = -3 /\ ~ y')
    assert prm.support_issubset(u, ['x', 'y'], fol)
    assert not prm.support_issubset(u, ['x'], fol)