コード例 #1
0
def test_cyclic_core_recursion():
    """One cyclic core."""
    fol = _fol.Context()
    fol.declare(x=(0, 1), y=(0, 1), z=(0, 1))
    s = r'''
        (
            \/ (z = 1  /\  y = 0)
            \/ (x = 0  /\  z = 1)
            \/ (y = 1  /\  x = 0)
            \/ (y = 1  /\  z = 0)
            \/ (x = 1  /\  z = 0)
            \/ (x = 1  /\  y = 0)
        )
        '''
    f = fol.add_expr(s)
    care = fol.true
    # setup variables and lattice
    prm = lat.setup_aux_vars(f, care, fol)
    lat.setup_lattice(prm, fol)
    # covering problem
    fcare = f | ~care
    x = lat.embed_as_implicants(f, prm, fol)
    y = lat.prime_implicants(fcare, prm, fol)
    # enumerative check
    enumerated_covers(x, y, prm, fol)
    # symbolically minimize
    mincovers = cov_enum.minimize(f, care, fol)
    n = len(mincovers)
    assert n == 2, (n, mincovers)
    for cover in mincovers:
        n = fol.count(cover)
        primes = list(fol.pick_iter(cover))
        assert n == 3, (n, primes)
コード例 #2
0
def test_enumerate_mincovers_below():
    """Test the function `enumerate_mincovers_below`."""
    fol = _fol.Context()
    fol.declare(x=(0, 5))
    u = fol.add_expr(r' x \in 0..1 ')
    care = fol.true
    prm = lat.setup_aux_vars(u, care, fol)
    lat.setup_lattice(prm, fol)
    x = fol.add_expr(r' a_x = 0 /\ b_x = 2 ')
    y = fol.add_expr(r'''
        \/ (a_x = 0 /\ b_x = 1)
        \/ (a_x = 0 /\ b_x = 3)
        \/ (a_x = 0 /\ b_x = 4)
        ''')
    cover_from_max = fol.add_expr(r'''
        a_x = 0 /\ b_x = 4
        ''')
    mincovers_below = cov_enum._enumerate_mincovers_below(
        cover_from_max, x, y, prm, fol)
    mincovers_below_ = cov_enum._enumerate_mincovers_below_set_based(
        cover_from_max, x, y, prm, fol)
    assert mincovers_below == mincovers_below_, mincovers_below
    r = fol.add_expr(r'''
        \/ (a_x = 0 /\ b_x = 3)
        \/ (a_x = 0 /\ b_x = 4)
        ''')
    mincovers_below_ = set(fol.assign_from(d) for d in fol.pick_iter(r))
    assert mincovers_below == mincovers_below_, (mincovers_below,
                                                 mincovers_below_)
コード例 #3
0
ファイル: cover.py プロジェクト: johnyf/omega
def cyclic_core(f, care, fol):
    """Shallow minimal cover, only up to cyclic core."""
    log.info('cyclic core computation')
    t0 = time.time()
    # assert
    assert f in fol.bdd, f
    assert care in fol.bdd, care
    assert care != fol.false, 'empty care set'
    assert f != fol.false, 'nothing to cover'
    assert f != fol.true or care != fol.true, (
        'no variables involved in problem')
    prm = lat.setup_aux_vars(f, care, fol)
    lat.setup_lattice(prm, fol)
    fcare = ~ care | f
    bab = _BranchAndBound(prm, fol)
    # covering problem
    x = lat.embed_as_implicants(f, prm, fol)
    y = lat.prime_implicants(fcare, prm, fol)
    # assert problem is feasible
    assert x != fol.false
    assert y != fol.false
    assert _covers(y, f, prm, fol)
    xcore, ycore, essential = _cyclic_core_fixpoint(
        x, y, bab, fol)
    if xcore == fol.false:
        assert _covers(essential, f, prm, fol)
    _print_cyclic_core(
        x, y, xcore, ycore, essential,
        t0, bab.prm, fol)
    return xcore, ycore, essential
コード例 #4
0
ファイル: cover.py プロジェクト: tichakornw/omega
def cyclic_core(f, care, fol):
    """Shallow minimal cover, only up to cyclic core."""
    log.info('cyclic core computation')
    t0 = time.time()
    # assert
    assert f in fol.bdd, f
    assert care in fol.bdd, care
    assert care != fol.false, 'empty care set'
    assert f != fol.false, 'nothing to cover'
    assert f != fol.true or care != fol.true, (
        'no variables involved in problem')
    prm = lat.setup_aux_vars(f, care, fol)
    lat.setup_lattice(prm, fol)
    fcare = ~care | f
    bab = _BranchAndBound(prm, fol)
    # covering problem
    x = lat.embed_as_implicants(f, prm, fol)
    y = lat.prime_implicants(fcare, prm, fol)
    # assert problem is feasible
    assert x != fol.false
    assert y != fol.false
    assert _covers(y, f, prm, fol)
    xcore, ycore, essential = _cyclic_core_fixpoint(x, y, bab, fol)
    if xcore == fol.false:
        assert _covers(essential, f, prm, fol)
    _print_cyclic_core(x, y, xcore, ycore, essential, t0, bab.prm, fol)
    return xcore, ycore, essential
コード例 #5
0
ファイル: cover.py プロジェクト: tichakornw/omega
def _assert_correct_cover(cover, f, care, fol):
    """Raise `AssertionError` if `cover` not of `f`."""
    prm = lat.setup_aux_vars(f, care, fol)
    # in implicant space
    low = care & ~f
    assert _none_covered(cover, low, prm, fol)
    # in concrete space
    g = _concretize_implicants(cover, prm, fol)
    assert (g & care) == (f & care)
コード例 #6
0
ファイル: cover.py プロジェクト: johnyf/omega
def _assert_correct_cover(cover, f, care, fol):
    """Raise `AssertionError` if `cover` not of `f`."""
    prm = lat.setup_aux_vars(f, care, fol)
    # in implicant space
    low = care & ~ f
    assert _none_covered(cover, low, prm, fol)
    # in concrete space
    g = _concretize_implicants(cover, prm, fol)
    assert (g & care) == (f & care)
コード例 #7
0
ファイル: cover.py プロジェクト: ciniks117/omega
def dumps_cover(
        cover, f, care, fol,
        latex=False,
        show_dom=False,
        show_limits=False,
        comment=True):
    """Return disjunction of orthotopes in `cover`, one per line.

    @param latex: use `pf.sty` commands
    @param show_dom: if `care` implies type hints,
        then conjoin type hints (`fol.vars[var]['dom']`)
    @param show_limits: conjoin limits of  bitfield values
    @param comment: if `True`, then list support of `f`, `cover`

    @rtype: `str`
    """
    prm = lat.setup_aux_vars(f, care, fol)
    c = list()
    if show_limits:
        r = tyh._list_limits(prm.x_vars, fol.vars)
        c.extend(r)
    show_dom = show_dom and _care_implies_type_hints(f, care, fol)
    if show_dom:
        r = tyh._list_type_hints(prm.x_vars, fol.vars)
        c.extend(r)
    else:
        log.info(
            'type hints omitted')
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom, latex=latex)
    s = stx.vertical_op(r, op='or', latex=latex, spacing=2)
    c.append(s)
    if care != fol.true:
        c.append('care expression')
    s = stx.vertical_op(c, op='and', latex=latex)
    f_vars = fol.support(f)
    care_vars = fol.support(care)
    s_comment = (
        '(* `f` depends on:  {f_vars} *)\n'
        '(* `care` depends on:  {care_vars} *)\n'
        '(* The minimal cover is: *)').format(
            f_vars=_comma_sorted(f_vars),
            care_vars=_comma_sorted(care_vars))
    if comment:
        s = '{comment}\n{s}'.format(comment=s_comment, s=s)
    # could add option to find minimal cover for care too
    # postcondition
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom)
    r = stx.disj(r)
    g = fol.add_expr(r)
    # ensure that `g` equals `f` inside `care`
    # `g` can be arbitrary outside of `care`
    assert (g & care) == (f & care), r
    return s
コード例 #8
0
ファイル: cover.py プロジェクト: ciniks117/omega
def minimize(f, care, fol):
    """Compute minimal DNF of predicate `f` over integers.

    @param f: predicate over integer-valued variables
    @param care: care set as predicate over same variables
    @type f, care: BDD node
    @type fol: `omega.symbolic.fol.Context`

    @return: minimal cover as BDD over parameters
    @rtype: BDD node
    """
    # reasons for permisiveness here:
    #
    # - enable inspecting env violations of assumption
    # - make errors visible
    # - use entire instantiation domain
    # - permit computing DNF for care set using same `fol.vars`
    # - tests
    if not _care_implies_type_hints(f, care, fol):
        log.warning('care set should imply type hints')
    # could let
    #     f &= care
    # but explicit is better.
    # Also, this permits working outside type hints.
    if not _f_implies_care(f, care, fol):
        log.warning('f should imply care set')
    if (f | ~ care) == fol.true:
        log.warning('f covers care set, so trivial cover')
    log.info('---- branching ----')
    path_cost = 0.0
    prm = lat.setup_aux_vars(f, care, fol)
    lat.setup_lattice(prm, fol)
    # covering problem
    fcare = f | ~ care
    # the slack is introduced by having more primes
    # (those for `fcare`) to cover the same minterms (`f`)
    x = lat.embed_as_implicants(f, prm, fol)
    y = lat.prime_implicants(fcare, prm, fol)
    bab = _BranchAndBound(prm, fol)
    # initialize upper bound
    bab.upper_bound = _upper_bound(
        x, y, prm.p_leq_q, prm.p_to_q, fol)
    # assert covers(bab.best_cover, f, prm, fol)
    cover, _ = _traverse(x, y, path_cost, bab, fol)
    if cover is None:
        cover, _ = _some_cover(x, y, prm.p_leq_q, p_to_q, fol)
    assert cover is not None
    cover = unfloors(cover, y, fol, bab)
    assert_is_a_cover_from_y(
        cover, y, f, prm, fol)
    low = care & ~ f
    assert _none_covered(cover, low, prm, fol)
    log.info('==== branching ==== ')
    return cover
コード例 #9
0
ファイル: cover.py プロジェクト: johnyf/omega
def minimize(f, care, fol):
    """Compute minimal DNF of predicate `f` over integers.

    @param f: predicate over integer-valued variables
    @param care: care set as predicate over same variables
    @type f, care: BDD node
    @type fol: `omega.symbolic.fol.Context`

    @return: minimal cover as BDD over parameters
    @rtype: BDD node
    """
    # reasons for permisiveness here:
    #
    # - enable inspecting env violations of assumption
    # - make errors visible
    # - use entire instantiation domain
    # - permit computing DNF for care set using same `fol.vars`
    # - tests
    if not _care_implies_type_hints(f, care, fol):
        log.warning('care set should imply type hints')
    # could let
    #     f &= care
    # but explicit is better.
    # Also, this permits working outside type hints.
    if not _f_implies_care(f, care, fol):
        log.warning('f should imply care set')
    if (f | ~ care) == fol.true:
        log.warning('f covers care set, so trivial cover')
    log.info('---- branching ----')
    path_cost = 0.0
    prm = lat.setup_aux_vars(f, care, fol)
    lat.setup_lattice(prm, fol)
    # covering problem
    fcare = f | ~ care
    # the slack is introduced by having more primes
    # (those for `fcare`) to cover the same minterms (`f`)
    x = lat.embed_as_implicants(f, prm, fol)
    y = lat.prime_implicants(fcare, prm, fol)
    bab = _BranchAndBound(prm, fol)
    # initialize upper bound
    bab.upper_bound = _upper_bound(
        x, y, prm.p_leq_q, prm.p_to_q, fol)
    # assert covers(bab.best_cover, f, prm, fol)
    cover, _ = _traverse(x, y, path_cost, bab, fol)
    if cover is None:
        cover, _ = _some_cover(x, y, prm.p_leq_q, p_to_q, fol)
    assert cover is not None
    cover = unfloors(cover, y, fol, bab)
    assert_is_a_cover_from_y(
        cover, y, f, prm, fol)
    low = care & ~ f
    assert _none_covered(cover, low, prm, fol)
    log.info('==== branching ==== ')
    return cover
コード例 #10
0
ファイル: cover.py プロジェクト: johnyf/omega
def dumps_cover(
        cover, f, care, fol,
        latex=False,
        show_dom=False,
        show_limits=False):
    """Return disjunction of orthotopes in `cover`, one per line.

    @param latex: use `pf.sty` commands
    @param show_dom: if `care` implies type hints,
        then conjoin type hints (`fol.vars[var]['dom']`)
    @param show_limits: conjoin limits of  bitfield values

    @rtype: `str`
    """
    prm = lat.setup_aux_vars(f, care, fol)
    c = list()
    if show_limits:
        r = tyh._list_limits(prm.x_vars, fol.vars)
        c.extend(r)
    show_dom = show_dom and _care_implies_type_hints(f, care, fol)
    if show_dom:
        r = tyh._list_type_hints(prm.x_vars, fol.vars)
        c.extend(r)
    else:
        log.info(
            'type hints omitted (care does not imply them)')
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom, latex=latex)
    s = stx.vertical_op(r, op='or', latex=latex)
    c.append(s)
    n_expr = len(r)
    if care != fol.true:
        c.append('care expression')
    s = stx.vertical_op(c, op='and', latex=latex)
    f_vars = fol.support(f)
    care_vars = fol.support(care)
    s = (
        '(* `f` depends on:  {f_vars} *)\n'
        '(* `care` depends on:  {care_vars} *)\n'
        '(* The minimal cover is: *)\n{s}').format(
            f_vars=_comma_sorted(f_vars),
            care_vars=_comma_sorted(care_vars),
            s=s)
    # could add option to find minimal cover for care too
    # postcondition
    r = lat.list_expr(
        cover, prm, fol, use_dom=show_dom)
    r = stx.disj(r)
    g = fol.add_expr(r)
    # ensure that `g` equals `f` inside `care`
    # `g` can be arbitrary outside of `care`
    assert (g & care) == (f & care), r
    return s
コード例 #11
0
def minimize(f, care, fol):
    """Compute minimal DNF of predicate `f` over integers.

    @param f: predicate over integer-valued variables
    @param care: care set as predicate over same variables
    @type f, care: BDD node
    @type fol: `omega.symbolic.fol.Context`

    @return: minimal covers as BDDs over parameters
    @rtype: set of BDD nodes
    """
    # reasons for permisiveness here:
    #
    # - enable inspecting env violations of assumption
    # - make errors visible
    # - use entire instantiation domain
    # - permit computing DNF for care set using same `fol.vars`
    # - tests
    if not cov._care_implies_type_hints(f, care, fol):
        log.warning('care set should imply type hints')
    # could let
    #     f &= care
    # but explicit is better.
    # Also, this permits working outside type hints.
    if not cov._f_implies_care(f, care, fol):
        log.warning('f should imply care set')
    if (f | ~care) == fol.true:
        log.warning('f covers care set, so trivial cover')
    log.info('---- branch and bound search ----')
    prm = lat.setup_aux_vars(f, care, fol)
    lat.setup_lattice(prm, fol)
    # covering problem
    fcare = f | ~care
    x = lat.embed_as_implicants(f, prm, fol)
    y = lat.prime_implicants(fcare, prm, fol)
    bab = cov._BranchAndBound(prm, fol)
    # initialize upper bound
    bab.upper_bound = cov._upper_bound(x, y, prm.p_leq_q, prm.p_to_q, fol)
    path_cost = 0.0
    mincovers = _cyclic_core_fixpoint_recursive(x, y, path_cost, bab, fol)
    # assert
    assert mincovers
    for cover in mincovers:
        cov.assert_is_a_cover_from_y(cover, y, f, prm, fol)
        low = care & ~f
        assert cov._none_covered(cover, low, prm, fol)
    log.info('==== branch and bound search ==== ')
    return mincovers
コード例 #12
0
ファイル: cover_test.py プロジェクト: tichakornw/omega
def test_setup_aux_vars():
    fol = _fol.Context()
    fol.declare(x=(-4, 5), y=(-7, 15))
    f = fol.add_expr('x = 2')
    care = fol.true
    prm = lat.setup_aux_vars(f, care, fol)
    vrs = prm.x_vars
    px = prm._px
    qx = prm._qx
    p_to_q = prm.p_to_q
    vrs_ = {'x'}
    assert vrs == vrs_, (vrs, vrs_)
    px_ = dict(x=dict(a='a_x', b='b_x'))
    assert px == px_, (px, px_)
    qx_ = dict(x=dict(a='u_x', b='v_x'))
    assert qx == qx_, (qx, qx_)
    p_to_q_ = dict(a_x='u_x', b_x='v_x')
    assert p_to_q == p_to_q_, (p_to_q, p_to_q_)
コード例 #13
0
ファイル: cover.py プロジェクト: ciniks117/omega
def _minimize_two_managers(f, care, fol):
    """Optimized version of `minimize` for large problems."""
    if not _care_implies_type_hints(f, care, fol):
        log.warning('care set should imply type hints')
    if not _f_implies_care(f, care, fol):
        log.warning('f should imply care set')
    if (f | ~ care) == fol.true:
        log.warning('f covers care set, so trivial cover')
    log.info('---- branching ----')
    path_cost = 0.0
    # x_vars, px, qx, p_to_q
    prm = lat.setup_aux_vars(f, care, fol)
    # manager where optimization happens
    fol_2 = type(fol)()
    fol_2.add_vars(fol.vars)
    # x (to be covered)
    log.info('embed implicants')
    x = lat.embed_as_implicants(f, prm, fol)
    x = fol.copy(x, fol_2)
    # covering problem
    fcare = f | ~ care
    lat.setup_lattice(prm, fol_2)
    # y (to use in cover)
    log.info('primes')
    fcare_2 = fol.copy(fcare, fol_2)
    y = lat.prime_implicants(fcare_2, prm, fol_2)
    del fcare_2
    bab = _BranchAndBound(prm, fol_2)
    # initialize upper bound
    bab.upper_bound = _upper_bound(
        x, y, prm.p_leq_q, prm.p_to_q, fol_2)
    # assert _covers(bab.best_cover, f, prm, fol_2)
    log.info('traverse')
    cover, _ = _traverse(x, y, path_cost, bab, fol_2)
    if cover is None:
        cover, _ = _some_cover(x, y, prm.p_leq_q, prm.p_to_q, fol_2)
    assert cover is not None
    cover = unfloors(cover, y, fol_2, bab)
    log.info('==== branching ==== ')
    del fcare, prm, bab
    cover = fol_2.copy(cover, fol)
    return cover
コード例 #14
0
ファイル: cover.py プロジェクト: johnyf/omega
def _minimize_two_managers(f, care, fol):
    """Optimized version of `minimize` for large problems."""
    if not _care_implies_type_hints(f, care, fol):
        log.warning('care set should imply type hints')
    if not _f_implies_care(f, care, fol):
        log.warning('f should imply care set')
    if (f | ~ care) == fol.true:
        log.warning('f covers care set, so trivial cover')
    log.info('---- branching ----')
    path_cost = 0.0
    # x_vars, px, qx, p_to_q
    prm = lat.setup_aux_vars(f, care, fol)
    # manager where optimization happens
    fol_2 = type(fol)()
    fol_2.add_vars(fol.vars)
    # x (to be covered)
    log.info('embed implicants')
    x = lat.embed_as_implicants(f, prm, fol)
    x = fol.copy(x, fol_2)
    # covering problem
    fcare = f | ~ care
    lat.setup_lattice(prm, fol_2)
    # y (to use in cover)
    log.info('primes')
    fcare_2 = fol.copy(fcare, fol_2)
    y = lat.prime_implicants(fcare_2, prm, fol_2)
    del fcare_2
    bab = _BranchAndBound(prm, fol_2)
    # initialize upper bound
    bab.upper_bound = _upper_bound(
        x, y, prm.p_leq_q, prm.p_to_q, fol_2)
    # assert _covers(bab.best_cover, f, prm, fol_2)
    log.info('traverse')
    cover, _ = _traverse(x, y, path_cost, bab, fol_2)
    if cover is None:
        cover, _ = _some_cover(x, y, prm.p_leq_q, prm.p_to_q, fol_2)
    assert cover is not None
    cover = unfloors(cover, y, fol_2, bab)
    log.info('==== branching ==== ')
    del fcare, prm, bab
    cover = fol_2.copy(cover, fol)
    return cover