Пример #1
0
def timed_xadd_engine(problem_generator, size_range, reduce_strategy=None):
    """ Execute the problems problem_generator(n) for each n in size_range, using the PyXaddEngine. """
    total_times = []
    result = []

    for size in size_range:
        density = problem_generator(size)
        engine = PyXaddEngine(density.domain,
                              density.support,
                              density.weight,
                              reduce_strategy=reduce_strategy)

        def execute_computation():
            starttime = time.time()
            result = engine.compute_volume(add_bounds=False)
            endtime = time.time()
            return result, (endtime - starttime)

        (res,
         runtime), error = run_exp_in_process(function=execute_computation,
                                              inputs=dict(),
                                              timeout_value=(None, None))

        if res is None:
            if isinstance(error, ProcessExpired):
                print(
                    "Experiment %s with size %s on xaddEngine raised exitcode %s."
                    % (problem_generator, size, error.exitcode))
            break
        else:
            result.append(res)
            total_times.append(runtime)

    return result, total_times
def test_latte_backend():
    print(xadd_installed)
    x, y = [Symbol(n, REAL) for n in "xy"]
    inequalities = [LinearInequality.from_smt(f) for f in [(x >= 0), (x <= y), (y <= 1)]]
    polynomial = Polynomial.from_smt((x*2/3 + 13/15) * (y*1/8 + x))
    domain = Domain.make([], ["x", "y"], [(0, 1), (0, 1)])
    result = LatteIntegrator().integrate(domain, inequalities, polynomial)
    xadd_result = EngineConvexIntegrationBackend(PyXaddEngine()).integrate(domain, inequalities, polynomial)
    print(result, xadd_result)
    assert result == pytest.approx(xadd_result, rel=0.001)
Пример #3
0
def test_trivial_weight_function_partial():
    # Support:  (a | b) & (~a | ~b) & (x >= 0) & (x <= y) & (y <= 10)
    # Weight:   1

    domain = Domain.make(["a", "b"], ["x", "y"], [(0, 1), (0, 1)])
    a, b, x, y = domain.get_symbols(domain.variables)
    support = (a | b) & (~a | ~b) & (x >= 0) & (x <= y) & (y <= 1)
    weight = Real(1.0)
    computed_volume = XsddEngine(
        domain=domain,
        support=support,
        weight=weight,
        convex_backend=EngineConvexIntegrationBackend(PyXaddEngine()),
    ).compute_volume()
    correction_volume_rej = RejectionEngine(domain, support, weight,
                                            1000000).compute_volume()
    correction_volume_xadd = PyXaddEngine(domain, support,
                                          weight).compute_volume()
    # print(correction_volume_rej, correction_volume_xadd, computed_volume)
    assert computed_volume == pytest.approx(correction_volume_rej, rel=ERROR)
    assert computed_volume == pytest.approx(correction_volume_xadd, rel=ERROR)
Пример #4
0
def test_partial_0b_2r_branch_weight():
    domain = Domain.make([], ["x", "y"], real_bounds=(0, 1))
    x, y = domain.get_symbols(domain.variables)
    support = (x >= 0.1) & (x <= 0.9) & (y >= 0.3) & (y <= 0.7)
    weight = Ite(x <= y, x, y * 3.17)

    engine = FactorizedXsddEngine(domain, support, weight)
    computed_volume = engine.compute_volume()

    should_be = PyXaddEngine(domain, support, weight).compute_volume()
    # print(computed_volume, should_be)
    assert computed_volume == pytest.approx(should_be, rel=ERROR)
Пример #5
0
def test_trivial_weight_function_partial_0b_1r_disjoint():
    domain = Domain.make([], ["x"], real_bounds=(0, 1))
    (x, ) = domain.get_symbols(domain.variables)
    support = (x >= 0.1) & (x <= 0.9) & ~((x >= 0.3) & (x <= 0.7))
    weight = Real(2.0)

    engine = FactorizedXsddEngine(domain, support, weight)
    computed_volume = engine.compute_volume()

    should_be = PyXaddEngine(domain, support, weight).compute_volume()
    # print(computed_volume, should_be)
    assert computed_volume == pytest.approx(should_be, rel=ERROR)
Пример #6
0
def get_test_engine_factory(domain,
                            formula,
                            weight_function,
                            allow_rejection=True):
    if check_installation_pyxadd():
        return PyXaddEngine(domain, formula, weight_function)
    elif check_installation_pa():
        return PredicateAbstractionEngine(domain, formula, weight_function)
    elif allow_rejection:
        return RejectionEngine(domain, formula, weight_function,
                               TEST_SAMPLE_COUNT)
    else:
        raise InstallError()
Пример #7
0
def test_volume():
    # Support:  (a | b) & (~a | ~b) & (x >= 0) & (x <= y) & (y <= 10)
    # Weight:   {
    #                a  b  (x>=0.5): 0.6*0.8*(0.5x+0.1y)  0.5 <= x <= y, x <= y <= 10
    #                a  b !(x>=0.5): 0.6*0.8*(0.1x+0.7y)  0 <= x <= [y, 0.5], x <= y <= 10
    #                a !b  (x>=0.5): 0.6*0.2*(0.5x+0.1y)  0.5 <= x <= y, x <= y <= 10
    #                a !b !(x>=0.5): 0.6*0.2*(0.1x+0.7y)  0 <= x <= [y, 0.5], x <= y <= 10
    #               !a  b  (x>=0.5): 0.4*0.8*(0.5x+0.1y)  0.5 <= x <= y, x <= y <= 10
    #               !a  b !(x>=0.5): 0.4*0.8*(0.1x+0.7y)  0 <= x <= [y, 0.5], x <= y <= 10
    #               !a !b  (x>=0.5): 0.4*0.2*(0.5x+0.1y)  0.5 <= x <= y, x <= y <= 10
    #               !a !b !(x>=0.5): 0.4*0.2*(0.1x+0.7y)  0 <= x <= [y, 0.5], x <= y <= 10
    # }

    # TODO What if we don't expand the Weight Function, only compile the support?
    # TODO => Can we reuse the SDD? It doesn't seem so... => Need multiple SDDs to use caching

    domain = Domain.make(["a", "b"], ["x", "y"], [(0, 1), (0, 1)])
    a, b, x, y = domain.get_symbols(domain.variables)
    support = (a | b) & (~a | ~b) & (x >= 0.0) & (x <= y) & (y <= 1.0)
    weight = (Ite(a, Real(0.6), Real(0.4)) * Ite(b, Real(0.8), Real(0.2)) *
              (Ite(
                  x >= Real(0.5),
                  Real(0.5) * x + Real(0.1) * y,
                  Real(0.1) * x + Real(0.7) * y,
              )))
    computed_volume = XsddEngine(
        domain=domain,
        support=support,
        weight=weight,
        convex_backend=EngineConvexIntegrationBackend(PyXaddEngine()),
    ).compute_volume()
    correction_volume_rej = RejectionEngine(domain, support, weight,
                                            1000000).compute_volume()
    correction_volume_xadd = PyXaddEngine(domain, support,
                                          weight).compute_volume()
    # print(correction_volume_rej, correction_volume_xadd, computed_volume)
    assert computed_volume == pytest.approx(correction_volume_rej, rel=ERROR)
    assert computed_volume == pytest.approx(correction_volume_xadd, rel=ERROR)
Пример #8
0
def get_engine(description, domain, support, weight):
    # type: (str, Domain, FNode, FNode) -> Engine
    parts = description.split(":")

    if parts[0].lower() == "pa":
        options = parse_options(parts[1:], "timeout")
        return PredicateAbstractionEngine(domain, support, weight, **options)
    if parts[0].lower() == "mpwmi":
        options = parse_options(parts[1:], "cache")
        return MPWMIEngine(domain, support, weight, **options)
    if parts[0].lower() == "rej":
        options = parse_options(parts[1:], "sample_count", "seed")
        return RejectionEngine(domain, support, weight, **options)
    if parts[0].lower() == "adapt":
        options = parse_options(parts[1:], "sample_count", "seed")
        return AdaptiveRejection(domain, support, weight, **options)
    if parts[0].lower() == "xadd":
        options = parse_options(parts[1:], "mode", "timeout")
        return XaddEngine(domain, support, weight, **options)
    if parts[0].lower() == "pyxadd":
        options = parse_options(parts[1:], "reduce")
        return PyXaddEngine(domain, support, weight, **options)
    if parts[0].lower() == "praise":
        # options = parse_options(parts[1:])
        return PraiseEngine(domain, support, weight)
    if parts[0].lower() == "xsdd":
        options = parse_options(
            parts[1:],
            "backend",
            "factorized",
            "find_conflicts",
            "ordered",
            "balance",
            "minimize",
        )
        backend_string = options.get("backend", None)
        if backend_string is None:
            backend = None
        else:
            parts = backend_string.split(".")
            if parts[0] == "rej":
                from .engines.rejection import RejectionIntegrator

                bb = int(parts[2]) if len(parts) > 2 else 0
                seed = int(parts[3]) if len(parts) > 3 else None
                backend = RejectionIntegrator(int(parts[1]), bb, seed=seed)
            elif parts[0] == "xadd":
                from .engines.xadd import XaddIntegrator

                backend = XaddIntegrator(parts[1] if len(parts) > 1 else None)
            elif parts[0] == "latte":
                from .engines.latte_backend import LatteIntegrator

                backend = LatteIntegrator()
            else:
                raise ValueError(
                    "Please specify a valid backend instead of {}".format(parts[0])
                )

        if "backend" in options:
            del options["backend"]

        # TODO figure out this
        # return XsddEngine(domain, support, weight, factorized=True,algebra=PyXaddAlgebra(), ordered=True)
        return XsddEngine(domain, support, weight, convex_backend=backend, **options)
Пример #9
0
def diabetes_example1():
    domain = Domain.make(["f0", "d0"], ["r0"], [(10, 45)])

    (
        f0,
        d0,
    ) = domain.get_bool_symbols()
    (r0, ) = domain.get_real_symbols()

    support = ((f0 & (((d0 | ~d0) & ~(r0 <= 35)) | ((r0 <= 35) & (~d0))))
               | (~f0 & (d0 & (r0 <= 35)))) & domain.get_bounds()
    # support_smaller = ((f0 & ((~(r0 <= 35)) | ~d0)) |
    #                    (~f0 & d0 & (r0 <= 35))) & \
    #                   domain.get_bounds()

    # support_smaller = ((f0 & ((~(r0 <= 35)) | ~d0))) & \
    #                   domain.get_bounds()

    support_smaller = ((f0 & ~(r0 <= 35) & ~d0) |
                       (f0 & (r0 <= 35) & ~d0)) & domain.get_bounds()

    weight_function = smt.Ite(f0, smt.Real(0.0001), smt.Real(0.00001)) * \
                      smt.Ite(d0, (r0/10)-1, 8-(r0/10)) * \
                      smt.Ite(r0 <= 35, -0.001*(r0-27)*(r0-27)+0.3, -0.001*(r0-27)*(r0-27)+0.3)
    #
    # weight_function_smaller = smt.Ite(f0, smt.Real(0.0001), smt.Real(0.00001)) * \
    #                           r0 *\
    #                           smt.Ite(r0 <= 35, -0.001*(r0)*(r0)+0.3, -0.001*(r0)*(r0)+0.3)
    weight_function_smaller = (
        smt.Real(0.00000001) * r0 * r0 * r0
    )  # * smt.Real(1000)  #<--- add this changes the result from 0.0 to 102
    density = Density(domain, support & domain.get_bounds(),
                      weight_function)  # weight_function)
    query = d0

    startTime = time.time()
    rejection_engine = RejectionEngine(density.domain,
                                       density.support,
                                       density.weight,
                                       sample_count=1000000)

    vol1 = rejection_engine.compute_volume()
    result1 = rejection_engine.compute_probability(query)
    endTime = time.time()
    time1 = endTime - startTime

    startTime = time.time()
    xadd_engine = PyXaddEngine(density.domain, density.support, density.weight)
    vol2 = xadd_engine.compute_volume(add_bounds=False)
    result2 = xadd_engine.compute_probability(query)
    endTime = time.time()
    time2 = endTime - startTime
    # XsddEngine
    algebra = PyXaddAlgebra(reduce_strategy=PyXaddAlgebra.FULL_REDUCE)
    mfxsdd = FXSDD(
        density.domain,
        density.support,
        density.weight,
        vtree_strategy=balanced,
        algebra=algebra,
        ordered=False,
    )
    startTime = time.time()
    vol3 = mfxsdd.compute_volume(add_bounds=False)
    result3 = mfxsdd.compute_probability(query=query, add_bounds=False)
    endTime = time.time()
    time3 = endTime - startTime

    print(f"R1 {result1}, time1: {time1}")
    print(f"R2 {result2}, time2: {time2}")
    print(f"R3 {result3}, time3: {time3}")
    print("")
    print(f"Vol1 {vol1}, time1: {time1}")
    print(f"Vol2 {vol2}, time2: {time2}")
    print(f"Vol3 {vol3}, time3: {time3}")
    return result1, result2, time1, time2