コード例 #1
0
def check_uncertainty3():

    s = """
mcdp {
  provides capacity [J]
  requires mass     [kg]

  required mass * Uncertain(2 J/kg, 3 J/kg) >= provided capacity
}
"""
    ndp = parse_ndp(s)
    dp = ndp.get_dp()
    R = dp.get_res_space()
    UR = UpperSets(R)
    dpl, dpu = get_dp_bounds(dp, 100, 100)
    f0 = 1.0  # J
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    print sl
    print su
    UR.check_leq(sl, su)

    real_lb = UpperSet(set([0.333333]), R)
    real_ub = UpperSet(set([0.500000]), R)

    # now dpl will provide a lower bound from below
    UR.check_leq(sl, real_lb)
    # and dpu will provide the upper bound from above
    UR.check_leq(real_ub, su)
コード例 #2
0
def check_uncertainty3():

    s = """
mcdp {
  provides capacity [J]
  requires mass     [kg]

  required mass * Uncertain(2 J/kg, 3 J/kg) >= provided capacity
}
"""
    ndp = parse_ndp(s)
    dp = ndp.get_dp()
    R = dp.get_res_space()
    UR = UpperSets(R)
    dpl, dpu = get_dp_bounds(dp, 100, 100)
    f0 = 1.0  # J
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    print sl
    print su
    UR.check_leq(sl, su)

    real_lb = UpperSet(set([0.333333]), R)
    real_ub = UpperSet(set([0.500000]), R)

    # now dpl will provide a lower bound from below
    UR.check_leq(sl, real_lb)
    # and dpu will provide the upper bound from above
    UR.check_leq(real_ub, su)
コード例 #3
0
def check_uncertainty2():
    ndp = parse_ndp("""
        mcdp {
            provides f1 [N]
            f1 <= Uncertain(1 N, 2 N)
        }
    """)
    
    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)

    R = dp.get_res_space()
    UR = UpperSets(R)
    f0 = 0.0  # N
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    UR.check_leq(sl, su)
    print sl
    print su

    f0 = 1.5  # N
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    UR.check_leq(sl, su)
    print sl
    print su
    feasible = UpperSet(set([()]), R)
    infeasible = UpperSet(set([]), R)
    sl_expected = feasible
    su_expected = infeasible
    print sl_expected
    print su_expected
    UR.check_equal(sl, sl_expected)
    UR.check_equal(su, su_expected)
コード例 #4
0
def check_uncertainty4():
    """ This will give an error somewhere """
    ndp = parse_ndp("""
mcdp {
    requires r1 [USD]
    r1 >= Uncertain(2 USD, 1 USD)
}

"""
 )
    # > DPSemanticError: Run-time check failed; wrong use of "Uncertain" operator.
    # > l: Instance of <type 'float'>.
    # >    2.0
    # > u: Instance of <type 'float'>.
    # >    1.0
    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)

    f = ()
    try:
        dpl.solve(f)
    except WrongUseOfUncertain:
        pass
    else:
        msg = 'Expected WrongUseOfUncertain.'
        raise_desc(Exception, msg)

    try:
        dpu.solve(f)
    except WrongUseOfUncertain:
        pass
    else:
        msg = 'Expected WrongUseOfUncertain.'
        raise_desc(Exception, msg)
コード例 #5
0
def check_uncertainty4():
    """ This will give an error somewhere """
    ndp = parse_ndp("""
mcdp {
    requires r1 [USD]
    r1 >= Uncertain(2 USD, 1 USD)
}

""")
    # > DPSemanticError: Run-time check failed; wrong use of "Uncertain" operator.
    # > l: Instance of <type 'float'>.
    # >    2.0
    # > u: Instance of <type 'float'>.
    # >    1.0
    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)

    f = ()
    try:
        dpl.solve(f)
    except WrongUseOfUncertain:
        pass
    else:  # pragma: no cover
        msg = 'Expected WrongUseOfUncertain.'
        raise_desc(Exception, msg)

    try:
        dpu.solve(f)
    except WrongUseOfUncertain:
        pass
    else:  # pragma: no cover
        msg = 'Expected WrongUseOfUncertain.'
        raise_desc(Exception, msg)
コード例 #6
0
def check_uncertainty2():
    ndp = parse_ndp("""
        mcdp {
            provides f1 [N]
            f1 <= Uncertain(1 N, 2 N)
        }
    """)

    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)

    R = dp.get_res_space()
    UR = UpperSets(R)
    f0 = 0.0  # N
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    UR.check_leq(sl, su)
    print sl
    print su

    f0 = 1.5  # N
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    UR.check_leq(sl, su)
    print sl
    print su
    feasible = UpperSet(set([()]), R)
    infeasible = UpperSet(set([]), R)
    sl_expected = feasible
    su_expected = infeasible
    print sl_expected
    print su_expected
    UR.check_equal(sl, sl_expected)
    UR.check_equal(su, su_expected)
コード例 #7
0
ファイル: drone_unc2.py プロジェクト: rusi/mcdp
def solve_stats(ndp):
    res = {}
    query = {
        "endurance": "1.5 hour",
        "velocity": "1 m/s",
        "extra_power": " 1 W",
        "extra_payload": "100 g",
        "num_missions": "100 []",
    }
    context = Context()
    f = convert_string_query(ndp=ndp, query=query, context=context)

    dp0 = ndp.get_dp()
    dpL, dpU = get_dp_bounds(dp0, nl=1, nu=1)

    F = dp0.get_fun_space()
    F.belongs(f)

    from mcdp import logger
    traceL = Tracer(logger=logger)
    resL = dpL.solve_trace(f, traceL)
    traceU = Tracer(logger=logger)
    resU = dpU.solve_trace(f, traceU)
    R = dp0.get_res_space()
    UR = UpperSets(R)
    print('resultsL: %s' % UR.format(resL))
    print('resultsU: %s' % UR.format(resU))

    res['traceL'] = traceL
    res['traceU'] = traceU
    res['resL'] = resL
    res['resU'] = resU
    res['nsteps'] = 100

    return res
コード例 #8
0
def solve_get_dp_from_ndp(basename, ndp, lower, upper, flatten=True):
    if flatten:
        ndp = ndp.flatten()

    dp = ndp.get_dp()

    if upper is not None:
        _, dp = get_dp_bounds(dp, 1, upper)
        basename += '-u-%03d' % upper
        assert lower is None

    if lower is not None:
        dp, _ = get_dp_bounds(dp, lower, 1)
        basename += '-l-%03d' % lower
        assert upper is None

    return basename, dp
コード例 #9
0
ファイル: solve_meat.py プロジェクト: AndreaCensi/mcdp
def solve_get_dp_from_ndp(basename, ndp, lower, upper, flatten=True):
    if flatten:
        ndp = ndp.flatten()

    dp = ndp.get_dp()

    if upper is not None:
        _, dp = get_dp_bounds(dp, 1, upper)
        basename += "-u-%03d" % upper
        assert lower is None

    if lower is not None:
        dp, _ = get_dp_bounds(dp, lower, 1)
        basename += "-l-%03d" % lower
        assert upper is None

    return basename, dp
コード例 #10
0
ファイル: test1.py プロジェクト: AndreaCensi/mcdp
 def _evaluate(self, ndp_name):
     imp = get_value_from_impdict(self.imp_dict, ndp_name)
     ndp = self.get_ndp(ndp_name)
     dp0 = ndp.get_dp()
     if self.nl is not None:
         dp, _ = get_dp_bounds(dp0, self.nl, 1)
     elif self.nu is not None:
         dp, _ = get_dp_bounds(dp0, 1, self.nu)
     else:
         dp = dp0
     I = dp.get_imp_space()
     try:
         I.belongs(imp)
     except NotBelongs as e:
         msg = 'Invalid value for implementation of %s.' % ndp_name.__str__()
         raise_wrapped(DPInternalError, e, msg, imp=imp, I=I)
     lf, ur = dp.evaluate(imp)
     return ndp, (lf, ur)
コード例 #11
0
ファイル: app_solver2.py プロジェクト: AndreaCensi/mcdp
    def process(self, request, string, nl, nu):
        l = self.get_library(request)
        parsed = l.parse_constant(string)

        space = parsed.unit
        value = parsed.value

        model_name = self.get_model_name(request)
        library = self.get_current_library_name(request)
        ndp, dp = self._get_ndp_dp(library, model_name)

        F = dp.get_fun_space()
        UR = UpperSets(dp.get_res_space())

        tu = get_types_universe()
        tu.check_leq(parsed.unit, F)

        f = express_value_in_isomorphic_space(parsed.unit, parsed.value, F)

        print('query: %s ...' % F.format(f))

        from mocdp import logger
        tracer = Tracer(logger=logger)

        dpl, dpu = get_dp_bounds(dp, nl, nu)

        intervals = False
        max_steps = 10000
        result_l, _trace = solve_meat_solve(tracer, ndp, dpl, f,
                                         intervals, max_steps, False)

        result_u, trace = solve_meat_solve(tracer, ndp, dpu, f,
                                         intervals, max_steps, False)


        key = (string, nl, nu)

        res = dict(result_l=result_l, result_u=result_u, dpl=dpl, dpu=dpu)
        self.solutions[key] = res

        res = {}

        e = cgi.escape

        res['output_space'] = e(space.__repr__() + '\n' + str(type(space)))
        res['output_raw'] = e(value.__repr__() + '\n' + str(type(value)))
        res['output_formatted'] = e(space.format(value))

        res['output_result'] = 'Lower: %s\nUpper: %s' % (UR.format(result_l),
                                                         UR.format(result_u))
        res['output_trace'] = str(trace)

        encoded = "nl=%s&nu=%s&string=%s" % (nl, nu, string)
        res['output_image'] = 'display.png?' + encoded
        res['ok'] = True

        return res
コード例 #12
0
ファイル: test1.py プロジェクト: AndreaCensi/mcdp
def plot_different_solutions(libname, ndpname, query, out, upper=None):
    if not os.path.exists(out):
        os.makedirs(out)
    library = get_test_library(libname)
    #library.use_cache_dir(os.path.join(out, 'cache'))
    context = Context()
    ndp = library.load_ndp(ndpname, context)

    context = library._generate_context_with_hooks()
    ndp_labelled = get_labelled_version(ndp)
    dp0 = ndp_labelled.get_dp()
    if upper is not None:
        _, dpU = get_dp_bounds(dp0, nl=1, nu=upper)
        dp = dpU
    else:
        dp = dp0

    M = dp.get_imp_space()

    with open(os.path.join(out, 'ndp.txt'), 'w') as f:
        f.write(ndp.repr_long())
    with open(os.path.join(out, 'M.txt'), 'w') as f:
        f.write(M.repr_long())
    with open(os.path.join(out, 'dp.txt'), 'w') as f:
        f.write(dp.repr_long())
    with open(os.path.join(out, 'dp0.txt'), 'w') as f:
        f.write(dp0.repr_long())

    f = convert_string_query(ndp=ndp, query=query, context=context)

    report = Report()

    res = dp.solve(f)
    print('num solutions: %s' % len(res.minimals))
    for ri, r in enumerate(res.minimals):
        ms = dp.get_implementations_f_r(f, r)

        for j, m in enumerate(ms):
            imp_dict = get_imp_as_recursive_dict(M, m)
            print imp_dict

            images_paths = library.get_images_paths()
            gv = GetValues(ndp=ndp, imp_dict=imp_dict, nu=upper, nl=1)

            gg = gvgen_from_ndp(ndp=ndp, style=STYLE_GREENREDSYM,
                                images_paths=images_paths,
                                plotting_info=gv)

            with report.subsection('%s-%s' % (ri, j)) as rr:
                gg_figure(rr, 'figure', gg, do_png=True, do_pdf=False,
                          do_svg=False, do_dot=False)


    fn = os.path.join(out, 'solutions.html')
    print('writing to %s' % fn)
    report.to_html(fn)
コード例 #13
0
ファイル: test1.py プロジェクト: rusi/mcdp
 def _evaluate(self, ndp_name):
     imp = get_value_from_impdict(self.imp_dict, ndp_name)
     ndp = self.get_ndp(ndp_name)
     dp0 = ndp.get_dp()
     if self.nl is not None:
         dp, _ = get_dp_bounds(dp0, self.nl, 1)
     elif self.nu is not None:
         dp, _ = get_dp_bounds(dp0, 1, self.nu)
     else:
         dp = dp0
     I = dp.get_imp_space()
     try:
         I.belongs(imp)
     except NotBelongs as e:
         msg = 'Invalid value for implementation of %s.' % ndp_name.__str__(
         )
         raise_wrapped(DPInternalError, e, msg, imp=imp, I=I)
     lf, ur = dp.evaluate(imp)
     return ndp, (lf, ur)
コード例 #14
0
ファイル: syntax_new_uncertainty.py プロジェクト: rusi/mcdp
def new_uncertainty01buse():
    s = """mcdp {
        requires r1 = 10 kg ± 0.5%
    }
    """
    ndp = parse_ndp(s)
    dp = ndp.get_dp()

    dpl, dpu = get_dp_bounds(dp, 1, 1)
    rl = dpl.solve(())
    ru = dpu.solve(())
    assert_almost_equal(list(rl.minimals)[0], 9.95)
    assert_almost_equal(list(ru.minimals)[0], 10.05)
コード例 #15
0
ファイル: basic.py プロジェクト: AndreaCensi/mcdp
def try_with_approximations(id_dp, dp, test):
    nl = nu = 3
    
    dpL, dpU = get_dp_bounds(dp, nl, nu)
    
    if '_lower_' in id_dp or '_upper_' in id_dp:
        msg = 'Recursion detected for %r %r' %(id_dp, dp)
        print(msg)
        return
    
    #print('approx: %s -> %s, %s' % (dp, dpL, dpU))    
    test(id_dp + '_lower_%s' % nl, dpL)
    test(id_dp + '_upper_%s' % nu, dpU)
コード例 #16
0
def try_with_approximations(id_dp, dp, test):
    nl = nu = 3

    dpL, dpU = get_dp_bounds(dp, nl, nu)

    if '_lower_' in id_dp or '_upper_' in id_dp:
        msg = 'Recursion detected for %r %r' % (id_dp, dp)
        print(msg)
        return

    #print('approx: %s -> %s, %s' % (dp, dpL, dpU))
    test(id_dp + '_lower_%s' % nl, dpL)
    test(id_dp + '_upper_%s' % nu, dpU)
コード例 #17
0
ファイル: syntax_new_uncertainty.py プロジェクト: rusi/mcdp
def new_uncertainty01usef():
    s = """mcdp {
        provides f1 = 10 kg ± 50 g
    }
    """
    ndp = parse_ndp(s)
    dp = ndp.get_dp()

    dpl, dpu = get_dp_bounds(dp, 1, 1)
    fl = dpl.solve_r(())
    fu = dpu.solve_r(())

    assert_almost_equal(list(fl.maximals)[0], 9.95)
    assert_almost_equal(list(fu.maximals)[0], 10.05)
コード例 #18
0
def check_uncertainty1():
    ndp = parse_ndp("""
        mcdp {
            requires r1 [USD]
            r1 >= Uncertain(1 USD, 2USD)
        }
    """)
    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)
    UR = UpperSets(dp.get_res_space())
    f = ()
    sl = dpl.solve(f)
    su = dpu.solve(f)
    UR.check_leq(sl, su)
コード例 #19
0
def check_uncertainty1():
    ndp = parse_ndp("""
        mcdp {
            requires r1 [USD]
            r1 >= Uncertain(1 USD, 2USD)
        }
    """)
    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)
    UR = UpperSets(dp.get_res_space())
    f = ()
    sl = dpl.solve(f)
    su = dpu.solve(f)
    UR.check_leq(sl, su)
コード例 #20
0
ファイル: eval_ndp_approx.py プロジェクト: AndreaCensi/mcdp
def eval_ndp_approx_lower(r, context):
    from mcdp_lang.eval_ndp_imp import eval_ndp
    from mcdp_dp.dp_transformations import get_dp_bounds

    nl = r.level
    ndp = eval_ndp(r.ndp, context)
    dp = ndp.get_dp()
    mcdp_dev_warning('make it better')
    dpl, _ = get_dp_bounds(dp, nl, 1)

    fnames = ndp.get_fnames()
    rnames = ndp.get_rnames()
    rnames = rnames if len(rnames) > 1 else rnames[0]
    fnames = fnames if len(fnames) > 1 else fnames[0]
    ndp2 = SimpleWrap(dpl, fnames, rnames)
    return ndp2
コード例 #21
0
def eval_ndp_approx_lower(r, context):
    from mcdp_lang.eval_ndp_imp import eval_ndp
    from mcdp_dp.dp_transformations import get_dp_bounds

    nl = r.level
    ndp = eval_ndp(r.ndp, context)
    dp = ndp.get_dp()
    mcdp_dev_warning('make it better')
    dpl, _ = get_dp_bounds(dp, nl, 1)

    fnames = ndp.get_fnames()
    rnames = ndp.get_rnames()
    rnames = rnames if len(rnames) > 1 else rnames[0]
    fnames = fnames if len(fnames) > 1 else fnames[0]
    ndp2 = SimpleWrap(dpl, fnames, rnames)
    return ndp2
コード例 #22
0
def check_repr(id_dp, dp):  # @UnusedVariable
    s1 = dp.repr_h_map()
    s2 = dp.repr_hd_map()
    print(s1)
    print(s2)
    if not '⟼' in s1 or not '⟼' in s2:
        msg = '%s: Malformed output' % (type(dp).__name__)
        raise_desc(ValueError, msg, repr_h_map=s1, repr_hd_map=s2)

    if not '_approx_' in id_dp and isinstance(dp, ApproximableDP):
        try:
            dpL, dpU = get_dp_bounds(dp, 4, 4)
            check_repr(id_dp + '_approx_Lower', dpL)
            check_repr(id_dp + '_approx_Upper', dpU)
        except (DPNotImplementedError, NotImplementedError):
            pass
コード例 #23
0
ファイル: syntax_new_uncertainty.py プロジェクト: rusi/mcdp
def new_uncertainty01use():
    s = """mcdp {
        requires r1 = 10 kg ± 50 g
    }
    """
    ndp = parse_ndp(s)
    dp = ndp.get_dp()

    dpl, dpu = get_dp_bounds(dp, 1, 1)
    rl = dpl.solve(())
    ru = dpu.solve(())

    R = dp.get_res_space()
    UR = UpperSets(R)
    UR.check_equal(rl, UpperSet([9.95], R))
    UR.check_equal(ru, UpperSet([10.05], R))
コード例 #24
0
ファイル: basic.py プロジェクト: AndreaCensi/mcdp
def check_repr(id_dp, dp):  # @UnusedVariable
    s1 = dp.repr_h_map()
    s2 = dp.repr_hd_map()
    print(s1)
    print(s2)
    if not '⟼' in s1 or not '⟼' in s2:
        msg = '%s: Malformed output' % (type(dp).__name__) 
        raise_desc(ValueError, msg, repr_h_map=s1, repr_hd_map=s2)

    if not '_approx_' in id_dp and isinstance(dp, ApproximableDP):
        try:
            dpL, dpU = get_dp_bounds(dp, 4, 4)
            check_repr(id_dp + '_approx_Lower', dpL)
            check_repr(id_dp + '_approx_Upper', dpU)
        except (DPNotImplementedError, NotImplementedError):
            pass
コード例 #25
0
def check_approx_res5():
    s = """
        mcdp {
            requires y [m]
            
            provides x [m]
            
            y >= approxu(x, 1 cm)
        }
    """
    ndp = parse_ndp(s)
    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)
    resl = dpl.solve(0.016)
    resu = dpu.solve(0.016)
    print resl
    print resu
    assert resl.minimals == set([0.01])
    assert resu.minimals == set([0.02])
コード例 #26
0
def check_uncertainty5():

    s = """
mcdp {
  provides capacity [Wh]
  requires mass     [kg]

  required mass * Uncertain(100 Wh/kg, 120 Wh/kg) >= provided capacity

}"""
    ndp = parse_ndp(s)
    dp = ndp.get_dp()
    R = dp.get_res_space()
    UR = UpperSets(R)
    dpl, dpu = get_dp_bounds(dp, 1000, 1000)
    f0 = 1.0  # J
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    UR.check_leq(sl, su)
コード例 #27
0
def check_approx_res5():
    s = """
        mcdp {
            requires y [m]
            
            provides x [m]
            
            y >= approxu(x, 1 cm)
        }
    """
    ndp = parse_ndp(s)
    dp = ndp.get_dp()
    dpl, dpu = get_dp_bounds(dp, 1, 1)
    resl = dpl.solve(0.016)
    resu = dpu.solve(0.016)
    print resl
    print resu
    assert resl.minimals == set([0.01])
    assert resu.minimals == set([0.02])
コード例 #28
0
ファイル: syntax_new_uncertainty.py プロジェクト: rusi/mcdp
def new_uncertainty_semantics01():
    s = """
    mcdp {
        a = instance mcdp {
            provides f = between 1W and 2W
        }
        provides f using a
    } """
    ndp = parse_ndp(s)
    dp = ndp.get_dp()

    dpl, dpu = get_dp_bounds(dp, 1, 1)
    rl = dpl.solve(1.5)
    ru = dpu.solve(1.5)
    feasible = lambda l: len(l.minimals) > 0

    UR = UpperSets(dp.get_res_space())
    UR.check_leq(rl, ru)
    assert feasible(rl)
    assert not feasible(ru)
コード例 #29
0
def check_uncertainty5():

    s = """
mcdp {
  provides capacity [Wh]
  requires mass     [kg]

  required mass * Uncertain(100 Wh/kg, 120 Wh/kg) >= provided capacity

}"""
    ndp = parse_ndp(s)
    dp = ndp.get_dp()
    R = dp.get_res_space()
    UR = UpperSets(R)
    dpl, dpu = get_dp_bounds(dp, 1000, 1000)
    f0 = 1.0  # J
    sl = dpl.solve(f0)
    su = dpu.solve(f0)
    UR.check_leq(sl, su)
    print sl
    print su
コード例 #30
0
ファイル: plot_approximations.py プロジェクト: rusi/mcdp
def go1(r, ns, dp, plot_nominal, axis):

    f = r.figure(cols=len(ns))

    for n in ns:
        dpL, dpU = get_dp_bounds(dp, n, n)

        f0 = 1.0
        R = dp.get_res_space()
        UR = UpperSets(R)
        space = PosetProduct((UR, UR))

        urL = dpL.solve(f0)
        urU = dpU.solve(f0)
        value = urL, urU

        plotter = get_best_plotter(space)
        figsize = (4, 4)
        with f.plot('plot_n%d' % n, figsize=figsize) as pylab:
            ieee_spines_zoom3(pylab)
            plotter.plot(pylab, axis, space, value)
            plot_nominal(pylab)
            pylab.axis(axis)
コード例 #31
0
def go1(r, ns, dp, plot_nominal, axis):

    f = r.figure(cols=len(ns))

    for n in ns:
        dpL, dpU = get_dp_bounds(dp, n, n)

        f0 = 1.0
        R = dp.get_res_space()
        UR = UpperSets(R)
        space = PosetProduct((UR, UR))

        urL = dpL.solve(f0)
        urU = dpU.solve(f0)
        value = urL, urU

        plotter = get_best_plotter(space)
        figsize = (4, 4)
        with f.plot("plot_n%d" % n, figsize=figsize) as pylab:
            ieee_spines_zoom3(pylab)
            plotter.plot(pylab, axis, space, value)
            plot_nominal(pylab)
            pylab.axis(axis)
コード例 #32
0
ファイル: drone_unc2.py プロジェクト: AndreaCensi/mcdp
def solve_stats(ndp):
    res = {} 
    query = {
        "endurance": "1.5 hour",
        "velocity":  "1 m/s",
        "extra_power": " 1 W",
        "extra_payload": "100 g",
        "num_missions": "100 []",
    }
    context = Context()
    f = convert_string_query(ndp=ndp, query=query, context=context)
    
    dp0 = ndp.get_dp()
    dpL, dpU = get_dp_bounds(dp0, nl=1, nu=1)


    F = dp0.get_fun_space()
    F.belongs(f)

    from mocdp import logger
    traceL = Tracer(logger=logger)
    resL = dpL.solve_trace(f, traceL)
    traceU = Tracer(logger=logger)
    resU = dpU.solve_trace(f, traceU)
    R = dp0.get_res_space()
    UR = UpperSets(R)
    print('resultsL: %s' % UR.format(resL))
    print('resultsU: %s' % UR.format(resU))
    
    res['traceL'] = traceL
    res['traceU'] = traceU
    res['resL'] = resL
    res['resU'] = resU
    res['nsteps'] = 100

    return res
コード例 #33
0
ファイル: syntax_power.py プロジェクト: AndreaCensi/mcdp
def check_power8():  # TODO: move to ther files

    ndp = parse_ndp("""
    mcdp {
      requires a [dimensionless]
      requires b [dimensionless]
      
      provides c [dimensionless]
      
      a + b >= c
    }
    """)
    dp = ndp.get_dp()
    print(dp.repr_long())
    nl = 5
    nu = 5
    dpL, dpU = get_dp_bounds(dp, nl, nu)

    print(dpL.repr_long())
    print(dpU.repr_long())
    f = 10.0
    UR = UpperSets(dp.get_res_space())
    Rl = dpL.solve(f)
    Ru = dpU.solve(f)
    assert_equal(len(Rl.minimals), nl)
    assert_equal(len(Ru.minimals), nu)
    print('Rl: %s' % UR.format(Rl))
    print('Ru: %s' % UR.format(Ru))
    UR.check_leq(Rl, Ru)
    
    import numpy as np
    for x in np.linspace(0, f, 100):
        y = f - x
        p = (x, y)

        Rl.belongs(p)
コード例 #34
0
def solve_stats(ndp, n, algo):

    res = {}
    query = {
        "travel_distance": " 2 km",
        "carry_payload": "100 g",
        "num_missions": "100 []",
    }
    context = Context()
    f = convert_string_query(ndp=ndp, query=query, context=context)

    dp0 = ndp.get_dp()
    dpL, dpU = get_dp_bounds(dp0, nl=n, nu=n)

    F = dp0.get_fun_space()
    F.belongs(f)

    logger = None
    InvMult2.ALGO = algo
    traceL = Tracer(logger=logger)
    resL = dpL.solve_trace(f, traceL)
    traceU = Tracer(logger=logger)
    resU = dpU.solve_trace(f, traceU)
    R = dp0.get_res_space()
    UR = UpperSets(R)
    print('resultsL: %s' % UR.format(resL))
    print('resultsU: %s' % UR.format(resU))

    res['traceL'] = traceL
    res['traceU'] = traceU
    res['resL'] = resL
    res['resU'] = resU
    res['n'] = n
    res['query'] = query

    return res
コード例 #35
0
ファイル: app_solver2.py プロジェクト: AndreaCensi/mcdp
        def go():
            xaxis = str(request.params['xaxis'])
            yaxis = str(request.params['yaxis'])

            model_name = self.get_model_name(request)
            library = self.get_current_library_name(request)
            ndp, dp = self._get_ndp_dp(library, model_name)

            fnames = ndp.get_fnames()
            rnames = ndp.get_rnames()

            if not xaxis in fnames:
                msg = 'Could not find function %r.' % xaxis
                raise_desc(ValueError, msg, fnames=fnames)

            if not yaxis in rnames:
                msg = 'Could not find resource %r.' % yaxis
                raise_desc(ValueError, msg, rnames=rnames)

            fsamples = get_samples(request, ndp)

            nl = int(request.params.get('nl', 1))
            nu = int(request.params.get('nu', 1))
            
            dpl, dpu = get_dp_bounds(dp, nl, nu)
            
            def extract_ri(r):
                if len(rnames) == 1:
                    return r
                else:
                    i = rnames.index(yaxis)
                    return r[i]
                
            ru_samples = []
            rl_samples = []
            for f in fsamples:
                rl = dpl.solve(f)
                ru = dpu.solve(f)
                
                mcdp_dev_warning('should use join instead of min')
        
                values = filter(extract_ri, rl.minimals)
                rli = min(values) if values else None
                values = filter(extract_ri, ru.minimals)
                rui = max(values) if values else None

                ru_samples.append(rui)
                rl_samples.append(rli)

            r = Report()
            f = r.figure()
            with f.plot("plot") as pylab:
                pylab.plot(fsamples, rl_samples, 'b.-')
                pylab.plot(fsamples, ru_samples, 'm.-')

                xlabel = xaxis + ' ' + format_unit(ndp.get_ftype(xaxis))
                pylab.xlabel(xlabel)
                ylabel = yaxis + ' ' + format_unit(ndp.get_rtype(yaxis))
                pylab.ylabel(ylabel)
                y_axis_extra_space(pylab)
                x_axis_extra_space(pylab)
                ax = pylab.gca()
                XCOLOR = 'green'
                YCOLOR = 'red'
                ax.tick_params(axis='x', colors=XCOLOR)
                ax.tick_params(axis='y', colors=YCOLOR)
                ax.yaxis.label.set_color(YCOLOR)
                ax.xaxis.label.set_color(XCOLOR)

                ax.spines['bottom'].set_color(XCOLOR)
                ax.spines['left'].set_color(YCOLOR)

            png_node = r.resolve_url('png')
            png_data = png_node.get_raw_data()

            return response_data(request=request, data=png_data,
                                 content_type='image/png')
コード例 #36
0
ファイル: dual.py プロジェクト: AndreaCensi/mcdp
def dual01_chain(id_dp, dp):
    try:
        with primitive_dp_test(id_dp, dp):
            print('Starting testing with %r' % id_dp)
            # get a chain of resources
            F = dp.get_fun_space()
            R = dp.get_res_space()
            
            # try to solve
            try: 
                dp.solve(F.witness())
                dp.solve_r(R.witness())
            except NotSolvableNeedsApprox:
                print('NotSolvableNeedsApprox - doing  lower bound ')
                n = 5
                dpL, dpU = get_dp_bounds(dp, nl=n, nu=n)
                dual01_chain(id_dp+'_L%s'%n, dpL)
                dual01_chain(id_dp+'_U%s'%n, dpU)
                return
            
            LF = LowerSets(F)
            UR = UpperSets(R)
        
            rchain = R.get_test_chain(n=8)
            poset_check_chain(R, rchain)
        
            try:
                lfchain = list(map(dp.solve_r, rchain))
                for lf in lfchain:
                    LF.belongs(lf)
            except NotSolvableNeedsApprox as e:
                print('skipping because %s'  % e)
                return
        
            try:
                poset_check_chain(LF, list(reversed(lfchain)))
                
            except ValueError as e:
                msg = 'The results of solve_r() are not a chain.'
                raise_wrapped(Exception, e, msg, chain=rchain, lfchain=lfchain)
        
            # now, for each functionality f, 
            # we know that the corresponding resource should be feasible
            
            for lf, r in zip(lfchain, rchain):
                print('')
                print('r: %s' % R.format(r))
                print('lf = h*(r) = %s' % LF.format(lf))
                
                for f in lf.maximals:
                    print('  f = %s' % F.format(f))
                    f_ur = dp.solve(f)
                    print('  f_ur = h(f) =  %s' % UR.format(f_ur))
                     
                    try:
                        f_ur.belongs(r)
                    except NotBelongs as e:
                        
                        try:
                            Rcomp.tolerate_numerical_errors = True
                            f_ur.belongs(r)
                            logger.info('In this case, there was a numerical error')
                            logger.info('Rcomp.tolerate_numerical_errors = True solved the problem')                    
                        except:
                            msg = ''
                            raise_wrapped(AssertionError, e, msg,
                                          lf=lf, r=r, f_ur=f_ur,
                                          r_repr=r.__repr__(),
                                          f_ur_minimals=f_ur.minimals.__repr__())
    finally:
        Rcomp.tolerate_numerical_errors = False
コード例 #37
0
ファイル: loading.py プロジェクト: rusi/mcdp
def friendly_solve(ndp, query, result_like='dict(str:str)', upper=None, lower=None):
    """
        query = dict(power=(100,"W"))
        result_like = dict(power="W")
        
        s = solve
    
    """
    #print('friendly_solve(upper=%s, lower=%s)' % (upper, lower))
    # TODO: replace with convert_string_query(ndp, query, context):
    fnames = ndp.get_fnames()
    rnames = ndp.get_rnames()

    if not len(rnames) >= 1:
        raise NotImplementedError()
    
    value = []

    for fname in fnames:
        if not fname in query:
            msg = 'Missing function'
            raise_desc(ValueError, msg, fname=fname, query=query, fnames=fnames)

        F = ndp.get_ftype(fname)
        q, qs = query[fname]
        s = '%s %s' % (q, qs)

        try:
            val = interpret_params_1string(s, F=F)
        except NotLeq as e:
            raise_wrapped(ValueError, e, 'wrong type', fname=fname)
            
        value.append(val)

    if len(fnames) == 1:
        value = value[0]
    else:
        value = tuple(value)

    if hasattr(ndp, '_cache_dp0'):
        dp0 = ndp._cache_dp0
    else:
        
        dp0 = ndp.get_dp()
        ndp._cache_dp0 = dp0
        
    if upper is not None:
        _, dp = get_dp_bounds(dp0, nl=1, nu=upper)

    elif lower is not None:
        dp, _ = get_dp_bounds(dp0, nl=lower, nu=1)
    else:
        dp = dp0
        
    F = dp.get_fun_space()
    F.belongs(value)

    from mcdp import logger
    trace = Tracer(logger=logger)
    res = dp.solve_trace(value, trace)
    R = dp.get_res_space()
    UR = UpperSets(R)
    print('value: %s' % F.format(value))
    print('results: %s' % UR.format(res))

    ares = []
    implementations = []

    for r in res.minimals:
        rnames = ndp.get_rnames()
        fr = dict()
        for rname, sunit in result_like.items():
            if not rname in rnames:
                msg = 'Could not find resource %r.' % rname
                raise_desc(ValueError, msg, rnames=rnames)
            i = rnames.index(rname)
            unit = interpret_string_as_space(sunit)
            Ri = ndp.get_rtype(rname)
            if len(rnames) > 1:
                ri = r[i]
            else:
                assert i == 0
                ri = r
            v = express_value_in_isomorphic_space(S1=Ri, s1=ri, S2=unit)
            fr[rname] = v
        
        ares.append(fr)
        
        ms = dp.get_implementations_f_r(value, r)
        implementations.append(ms)
        
    return ares, implementations
コード例 #38
0
ファイル: test1.py プロジェクト: rusi/mcdp
def plot_different_solutions(libname, ndpname, query, out, upper=None):
    if not os.path.exists(out):
        os.makedirs(out)
    library = get_test_library(libname)
    #library.use_cache_dir(os.path.join(out, 'cache'))
    context = Context()
    ndp = library.load_ndp(ndpname, context)

    context = library._generate_context_with_hooks()
    ndp_labelled = get_labelled_version(ndp)
    dp0 = ndp_labelled.get_dp()
    if upper is not None:
        _, dpU = get_dp_bounds(dp0, nl=1, nu=upper)
        dp = dpU
    else:
        dp = dp0

    M = dp.get_imp_space()

    with open(os.path.join(out, 'ndp.txt'), 'w') as f:
        f.write(ndp.repr_long())
    with open(os.path.join(out, 'M.txt'), 'w') as f:
        f.write(M.repr_long())
    with open(os.path.join(out, 'dp.txt'), 'w') as f:
        f.write(dp.repr_long())
    with open(os.path.join(out, 'dp0.txt'), 'w') as f:
        f.write(dp0.repr_long())

    f = convert_string_query(ndp=ndp, query=query, context=context)

    report = Report()

    res = dp.solve(f)
    print('num solutions: %s' % len(res.minimals))
    for ri, r in enumerate(res.minimals):
        ms = dp.get_implementations_f_r(f, r)

        for j, m in enumerate(ms):
            imp_dict = get_imp_as_recursive_dict(M, m)
            logger.info(imp_dict)

            images_paths = library.get_images_paths()
            image_source = ImagesFromPaths(images_paths)
            gv = GetValues(ndp=ndp, imp_dict=imp_dict, nu=upper, nl=1)

            gg = gvgen_from_ndp(ndp=ndp,
                                style=STYLE_GREENREDSYM,
                                image_source=image_source,
                                plotting_info=gv)

            with report.subsection('%s-%s' % (ri, j)) as rr:
                gg_figure(rr,
                          'figure',
                          gg,
                          do_png=True,
                          do_pdf=False,
                          do_svg=False,
                          do_dot=False)

    fn = os.path.join(out, 'solutions.html')
    print('writing to %s' % fn)
    report.to_html(fn)
コード例 #39
0
ファイル: test_imp_space.py プロジェクト: rusi/mcdp
def test_imp_space_2():
    ndp0 = parse_ndp("""
addmake(root: code mcdp_comp_tests.test_imp_space.make_root)
mcdp {
    a = instance 
        
        addmake(root: code mcdp_comp_tests.test_imp_space.make_a)
        mcdp {
        
        a2 = instance 
        
        addmake(root: code mcdp_comp_tests.test_imp_space.make_a2) 
        catalogue {
            provides capacity [J]
            requires mass [g]
            
            model1 | 1 J | 200 g
            model2 | 2 J | 300 g
        }
        
        provides capacity using a2
        requires mass >= 10g + a2.mass 
    }
    
    b = instance 
    addmake(root: code mcdp_comp_tests.test_imp_space.make_b)
    catalogue {
        provides capacity [J]
        requires mass [g]
        
        model3 | 1 J | 200 g
        model4 | 2 J | 300 g
    }
    
    provides capacity <= a.capacity + b.capacity
    requires mass >= a.mass + b.mass
}

    """)
    assert isinstance(ndp0, CompositeNamedDP)
    ndp_labeled = get_labelled_version(ndp0)
    ndp_canonical = cndp_makecanonical(ndp_labeled)
    dp0 = ndp_canonical.get_dp()
#     print dp0.repr_long()
    dp, _ = get_dp_bounds(dp0, 5, 5)
    f = 0.0
    R = dp.get_res_space()
    ur = dp.solve(f)
    I = dp.get_imp_space()
    assert isinstance(I, SpaceProduct)

    print('I: %s' % I)
    print('get_names_used: %s' % get_names_used(I))

    for r in ur.minimals:
        print('r = %s' % R.format(r))
        imps = dp.get_implementations_f_r(f, r)
        print('imps: %s' % imps)

        for imp in imps:
            I.belongs(imp)
            imp_dict = get_imp_as_recursive_dict(I, imp)  # , ignore_hidden=False)
            print('imp dict: %r' % imp_dict)
            assert set(imp_dict) == set(['a', 'b', '_sum1', '_invplus1', '_fun_capacity', '_res_mass']), imp_dict
            assert set(imp_dict['a']) == set(['_plus1', 'a2', '_fun_capacity', '_res_mass' ]), imp_dict['a']
            context = {}
            artifact = ndp_make(ndp0, imp_dict, context)
            print('artifact: %s' % artifact)
コード例 #40
0
def dual01_chain(id_dp, dp):
    try:
        with primitive_dp_test(id_dp, dp):
            print('Starting testing with %r' % id_dp)
            # get a chain of resources
            F = dp.get_fun_space()
            R = dp.get_res_space()
            
            # try to solve
            try: 
                dp.solve(F.witness())
                dp.solve_r(R.witness())
            except NotSolvableNeedsApprox:
                print('NotSolvableNeedsApprox - doing  lower bound ')
                n = 5
                dpL, dpU = get_dp_bounds(dp, nl=n, nu=n)
                dual01_chain(id_dp+'_L%s'%n, dpL)
                dual01_chain(id_dp+'_U%s'%n, dpU)
                return
            
            LF = LowerSets(F)
            UR = UpperSets(R)
        
            rchain = R.get_test_chain(n=8)
            poset_check_chain(R, rchain)
        
            try:
                lfchain = list(map(dp.solve_r, rchain))
                for lf in lfchain:
                    LF.belongs(lf)
            except NotSolvableNeedsApprox as e:
                print('skipping because %s'  % e)
                return
        
            try:
                poset_check_chain(LF, list(reversed(lfchain)))
                
            except ValueError as e:
                msg = 'The results of solve_r() are not a chain.'
                raise_wrapped(Exception, e, msg, chain=rchain, lfchain=lfchain)
        
            # now, for each functionality f, 
            # we know that the corresponding resource should be feasible
            
            for lf, r in zip(lfchain, rchain):
                print('')
                print('r: %s' % R.format(r))
                print('lf = h*(r) = %s' % LF.format(lf))
                
                for f in lf.maximals:
                    print('  f = %s' % F.format(f))
                    f_ur = dp.solve(f)
                    print('  f_ur = h(f) =  %s' % UR.format(f_ur))
                     
                    try:
                        f_ur.belongs(r)
                    except NotBelongs as e:
                        
                        try:
                            Rcomp.tolerate_numerical_errors = True
                            f_ur.belongs(r)
                            logger.info('In this case, there was a numerical error')
                            logger.info('Rcomp.tolerate_numerical_errors = True solved the problem')                    
                        except:
                            msg = ''
                            raise_wrapped(AssertionError, e, msg,
                                          lf=lf, r=r, f_ur=f_ur,
                                          r_repr=r.__repr__(),
                                          f_ur_minimals=f_ur.minimals.__repr__())
    finally:
        Rcomp.tolerate_numerical_errors = False
コード例 #41
0
ファイル: test_imp_space.py プロジェクト: AndreaCensi/mcdp
def test_imp_space_2():
    ndp0 = parse_ndp("""
addmake(root: code mocdp.comp.tests.test_imp_space.make_root)
mcdp {
    a = instance 
        
        addmake(root: code mocdp.comp.tests.test_imp_space.make_a)
        mcdp {
        
        a2 = instance 
        
        addmake(root: code mocdp.comp.tests.test_imp_space.make_a2) 
        catalogue {
            provides capacity [J]
            requires mass [g]
            
            model1 | 1 J | 200 g
            model2 | 2 J | 300 g
        }
        
        provides capacity using a2
        requires mass >= 10g + a2.mass 
    }
    
    b = instance 
    addmake(root: code mocdp.comp.tests.test_imp_space.make_b)
    catalogue {
        provides capacity [J]
        requires mass [g]
        
        model3 | 1 J | 200 g
        model4 | 2 J | 300 g
    }
    
    provides capacity <= a.capacity + b.capacity
    requires mass >= a.mass + b.mass
}

    """)
    assert isinstance(ndp0, CompositeNamedDP)
    ndp_labeled = get_labelled_version(ndp0)
    ndp_canonical = cndp_makecanonical(ndp_labeled)
    dp0 = ndp_canonical.get_dp()
#     print dp0.repr_long()
    dp, _ = get_dp_bounds(dp0, 5, 5)
    f = 0.0
    R = dp.get_res_space()
    ur = dp.solve(f)
    I = dp.get_imp_space()
    assert isinstance(I, SpaceProduct)

    print('I: %s' % I)
    print('get_names_used: %s' % get_names_used(I))

    for r in ur.minimals:
        print('r = %s' % R.format(r))
        imps = dp.get_implementations_f_r(f, r)
        print('imps: %s' % imps)

        for imp in imps:
            I.belongs(imp)
            imp_dict = get_imp_as_recursive_dict(I, imp)  # , ignore_hidden=False)
            print('imp dict: %r' % imp_dict)
            assert set(imp_dict) == set(['a', 'b', '_sum1', '_invplus1', '_fun_capacity', '_res_mass']), imp_dict
            assert set(imp_dict['a']) == set(['_plus1', 'a2', '_fun_capacity', '_res_mass' ]), imp_dict['a']
            context = {}
            artifact = ndp_make(ndp0, imp_dict, context)
            print('artifact: %s' % artifact)
コード例 #42
0
ファイル: loading.py プロジェクト: AndreaCensi/mcdp
def friendly_solve(ndp, query, result_like='dict(str:str)', upper=None, lower=None):
    """
        query = dict(power=(100,"W"))
        result_like = dict(power="W")
        
        s = solve
    
    """
    #print('friendly_solve(upper=%s, lower=%s)' % (upper, lower))
    # TODO: replace with convert_string_query(ndp, query, context):
    fnames = ndp.get_fnames()
    rnames = ndp.get_rnames()

    if not len(rnames) >= 1:
        raise NotImplementedError()
    
    value = []

    for fname in fnames:
        if not fname in query:
            msg = 'Missing function'
            raise_desc(ValueError, msg, fname=fname, query=query, fnames=fnames)

        F = ndp.get_ftype(fname)
        q, qs = query[fname]
        s = '%s %s' % (q, qs)

        try:
            val = interpret_params_1string(s, F=F)
        except NotLeq as e:
            raise_wrapped(ValueError, e, 'wrong type', fname=fname)
            
        value.append(val)

    if len(fnames) == 1:
        value = value[0]
    else:
        value = tuple(value)

    if hasattr(ndp, '_cache_dp0'):
        dp0 = ndp._cache_dp0
    else:
        
        dp0 = ndp.get_dp()
        ndp._cache_dp0 = dp0
        
    if upper is not None:
        _, dp = get_dp_bounds(dp0, nl=1, nu=upper)

    elif lower is not None:
        dp, _ = get_dp_bounds(dp0, nl=lower, nu=1)
    else:
        dp = dp0
        
    F = dp.get_fun_space()
    F.belongs(value)

    from mocdp import logger
    trace = Tracer(logger=logger)
    res = dp.solve_trace(value, trace)
    R = dp.get_res_space()
    UR = UpperSets(R)
    print('value: %s' % F.format(value))
    print('results: %s' % UR.format(res))

    ares = []
    implementations = []

    for r in res.minimals:
        rnames = ndp.get_rnames()
        fr = dict()
        for rname, sunit in result_like.items():
            if not rname in rnames:
                msg = 'Could not find resource %r.' % rname
                raise_desc(ValueError, msg, rnames=rnames)
            i = rnames.index(rname)
            unit = interpret_string_as_space(sunit)
            Ri = ndp.get_rtype(rname)
            if len(rnames) > 1:
                ri = r[i]
            else:
                assert i == 0
                ri = r
            v = express_value_in_isomorphic_space(S1=Ri, s1=ri, S2=unit)
            fr[rname] = v
        
        ares.append(fr)
        
        ms = dp.get_implementations_f_r(value, r)
        implementations.append(ms)
        
    return ares, implementations
コード例 #43
0
    def process_ftor(self, e, string, do_approximations, nl, nu):
        mcdp_library = library_from_env(e)
        parsed = mcdp_library.parse_constant(string)

        space = parsed.unit
        value = parsed.value

        ndp, dp = self.get_ndp_dp_e(e)

        F = dp.get_fun_space()
        UR = UpperSets(dp.get_res_space())

        try:
            f = parsed.cast_value(F)
        except NotLeq:
            msg = 'Space %s cannot be converted to %s' % (parsed.unit, F)
            raise DPSemanticError(msg)

        logger.info('query rtof: %s ...' % F.format(f))

        tracer = Tracer(logger=logger)

        intervals = False
        max_steps = 10000
        res = {}

        if do_approximations:

            dpl, dpu = get_dp_bounds(dp, nl, nu)

            result_l, _trace = solve_meat_solve_ftor(tracer, ndp, dpl, f,
                                                     intervals, max_steps,
                                                     False)

            result_u, trace = solve_meat_solve_ftor(tracer, ndp, dpu, f,
                                                    intervals, max_steps,
                                                    False)

            data = dict(result_l=result_l, result_u=result_u, dpl=dpl, dpu=dpu)

            res['output_result'] = 'Lower: %s\nUpper: %s' % (
                UR.format(result_l), UR.format(result_u))

        else:
            try:
                result, trace = solve_meat_solve_ftor(tracer, ndp, dp, f,
                                                      intervals, max_steps,
                                                      False)
            except NotSolvableNeedsApprox:
                msg = 'The design problem has infinite antichains. Please use approximations.'
                raise NeedsApprox(msg)
            data = dict(result=result, dp=dp)

            res['output_result'] = UR.format(result)

        e = cgi.escape
        res['output_space'] = e(space.__repr__() + '\n' + str(type(space)))
        res['output_raw'] = e(value.__repr__() + '\n' + str(type(value)))
        res['output_formatted'] = e(space.format(value))
        res['output_trace'] = str(trace)
        return data, res
コード例 #44
0
        def go():
            xaxis = str(e.request.params['xaxis'])
            yaxis = str(e.request.params['yaxis'])

            ndp, dp = self.get_ndp_dp_e(e)

            fnames = ndp.get_fnames()
            rnames = ndp.get_rnames()

            if not xaxis in fnames:
                msg = 'Could not find function %r.' % xaxis
                raise_desc(ValueError, msg, fnames=fnames)

            if not yaxis in rnames:
                msg = 'Could not find resource %r.' % yaxis
                raise_desc(ValueError, msg, rnames=rnames)

            fsamples = get_samples(e.request, ndp)

            nl = int(e.request.params.get('nl', 1))
            nu = int(e.request.params.get('nu', 1))

            dpl, dpu = get_dp_bounds(dp, nl, nu)

            def extract_ri(r):
                if len(rnames) == 1:
                    return r
                else:
                    i = rnames.index(yaxis)
                    return r[i]

            ru_samples = []
            rl_samples = []
            for f in fsamples:
                rl = dpl.solve(f)
                ru = dpu.solve(f)

                mcdp_dev_warning('should use join instead of min')

                values = filter(extract_ri, rl.minimals)
                rli = min(values) if values else None
                values = filter(extract_ri, ru.minimals)
                rui = max(values) if values else None

                ru_samples.append(rui)
                rl_samples.append(rli)

            r = Report()
            f = r.figure()
            with f.plot("plot") as pylab:
                pylab.plot(fsamples, rl_samples, 'b.-')
                pylab.plot(fsamples, ru_samples, 'm.-')

                xlabel = xaxis + ' ' + format_unit(ndp.get_ftype(xaxis))
                pylab.xlabel(xlabel)
                ylabel = yaxis + ' ' + format_unit(ndp.get_rtype(yaxis))
                pylab.ylabel(ylabel)
                y_axis_extra_space(pylab)
                x_axis_extra_space(pylab)
                ax = pylab.gca()
                XCOLOR = 'green'
                YCOLOR = 'red'
                ax.tick_params(axis='x', colors=XCOLOR)
                ax.tick_params(axis='y', colors=YCOLOR)
                ax.yaxis.label.set_color(YCOLOR)
                ax.xaxis.label.set_color(XCOLOR)

                ax.spines['bottom'].set_color(XCOLOR)
                ax.spines['left'].set_color(YCOLOR)

            png_node = r.resolve_url('png')
            png_data = png_node.get_raw_data()

            return response_data(request=e.request,
                                 data=png_data,
                                 content_type='image/png')