def alternatives(): parse_ndp(""" mcdp { # two linear response # 0J => 0, 0 # two slutions for 12.5 g # 100J => mcdp battery1 = mcdp { provides capacity [J] requires mass [kg] m0 = 5 g specific_energy = 1 J / kg mass >= capacity / specific_energy + m0 } mcdp battery2 = mcdp { provides capacity [J] requires mass [kg] m0 = 10 g specific_energy = 0.6 J / kg mass >= capacity / specific_energy + m0 } sub battery = instance choose(b1: battery1, b2: battery2) requires mass for battery provides capacity using battery } """)
def check_subtraction2_contexts(): """ We cannot do propagation of constants inside contexts """ s = """ mcdp { v2 = 2 g t = instance mcdp { v1 = 10 g v = v1 - v2 requires x = v } } """ parse_ndp(s) s = """ mcdp { v1 = 10 g mcdp { v2 = 2 g t = instance mcdp { v = v1 - v2 requires x = v } } } """ parse_ndp(s)
def new_uncertainty11(): s = """mcdp { c = 10 kg δ = 50 g requires x = between c-δ and c+δ } """ parse_ndp(s)
def new_uncertainty09(): s = """mcdp { c = 10 kg δ = 50 g provides f = between c-δ and c+δ } """ parse_ndp(s)
def check_uncertainty7(): s = """ mcdp { provides capacity [m] requires mass [m] energy_density = 1 # nat required mass * energy_density >= provided capacity } """ parse_ndp(s)
def check_uncertainty8(): s = """ mcdp { provides capacity [m] requires mass [m] energy_density = between 1 and 2 required mass >= provided capacity * energy_density } """ parse_ndp(s)
def check_uncertainty6(): s = """ mcdp { provides capacity [kWh] requires mass [g] requires cost [$] energy_density = between 140 kWh/kg and 160 kWh/kg required mass * energy_density >= provided capacity } """ parse_ndp(s)
def check_lang_namedtuple2(): parse_ndp(""" mcdp { provides capability [ product(weight: g, energy: J) ] capability <= < 1g, 1J> } """)
def power1(): parse_wrap_check('x^2', Syntax.rvalue_power_expr) parse_wrap_check('²', Syntax.superscripts) parse_wrap_check('x²', Syntax.rvalue_power_expr) parse_ndp(""" mcdp { provides f [dimensionless] requires r [dimensionless] (provided f)² <= required r } """)
def check_subtraction2_contexts_a(): """ We cannot do propagation of constants inside contexts """ s = """ mcdp { v2 = 2 g t = instance mcdp { v1 = 10 g v = v1 - v2 requires x = v } } """ parse_ndp(s)
def check_subtraction2_contexts_b(): s = """ mcdp { v1 = 10 g mcdp { v2 = 2 g t = instance mcdp { v = v1 - v2 requires x = v } } } """ parse_ndp(s)
def check_lang_namedtuple4(): parse_ndp(""" mcdp { provides capability [ product(weight: g, energy: J) ] (capability).weight <= 1g # (capability).energy <= 1J } """)
def check_take_optim1(): parse_ndp(""" mcdp { provides f [s x J] requires r1 [s] requires r2 [J] required r1 >= take(provided f, 0) required r2 >= take(provided f, 1) } """)
def check_lang_namedtuple5(): parse_wrap(Syntax.fvalue_label_indexing, "capability..weight ")[0] parse_ndp(""" mcdp { requires capability [ product(weight: g, energy: J) ] capability..weight >= 1g capability..energy >= 1J } """)
def check_take_optim2(): parse_ndp(""" mcdp { requires r [s x J] provides f1 [s] provides f2 [J] provided f1 <= take(required r, 0) provided f2 <= take(required r, 1) } """)
def check_uncertainty7_uncertain(): string = "energy_density = between 1 and 2" parse_wrap(Syntax.setname_constant_uncertain, string) expr = parse_wrap(Syntax.line_expr, string)[0] logger.debug('TMP:\n' + recursive_print(expr)) s = """ mcdp { provides capacity [m] requires mass [m] energy_density = between 1 and 2 required mass * energy_density >= provided capacity } """ parse_ndp(s)
def check_sets3(): parse_ndp(""" mcdp { mcdp simple_cell = catalogue { provides voltage [set-of(V)] provides capacity [J] requires cost [$] requires mass [kg] model1 | {1.5 V} | 1 J | 5 $ | 0.20 kg model2 | {1.5 V} | 1 J | 5 $ | 0.20 kg model3 | {5.0 V} | 1 J | 5 $ | 0.30 kg } mcdp cell_plus_converter = mcdp { provides voltage [set-of(V)] provides capacity [J] requires cost [$] requires mass [kg] converter = instance catalogue { provides voltage_out [set-of(V)] requires voltage_in [set-of(V)] requires cost [$] requires mass [g] step_up1 |{5 V} | {1.5 V} | 5 $ | 20 g step_up2 |{12 V} | {1.5 V} | 10 $ | 20 g step_up2 |{12 V, 5 V} | {1.5 V} | 10 $ | 20 g } cell = instance simple_cell voltage <= converter.voltage_out converter.voltage_in <= cell.voltage mass >= cell.mass + converter.mass cost >= cell.cost + converter.cost capacity <= cell.capacity } battery = instance choose(simple: simple_cell, conv: cell_plus_converter) } """)
def check_anyof2(): ndp = parse_ndp(""" mcdp { provides x [g x g] x <= any-of({<0g,1g>, <1g, 0g>}) } """) dp = ndp.get_dp() R = dp.get_res_space() F = dp.get_fun_space() UR = UpperSets(R) res = dp.solve((0.5, 0.5)) l = LowerSet(P=F, maximals=[(0.0, 1.0), (1.0, 0.0)]) l.belongs((0.0, 0.5)) l.belongs((0.5, 0.0)) UR.check_equal(res, UpperSet([], R)) res = dp.solve((0.0, 0.5)) UR.check_equal(res, UpperSet([()], R)) res = dp.solve((0.5, 0.0)) UR.check_equal(res, UpperSet([()], R))
def check_new_loop1(): ndp = parse_ndp(""" mcdp { provides m [Nat] f = instance mcdp { provides a [Nat] requires x [Nat] requires y [Nat] x + y >= a } f.a >= square(f.x) + square(f.y) + m requires x, y for f } """) r = cndp_abstract_loop2(ndp) print r
def go(): librarian = Librarian() librarian.find_libraries('../..') library = librarian.load_library('droneD_complete_templates') library.use_cache_dir('_cached/drone_unc2') context = library._generate_context_with_hooks() res = {} res['intervals'] = [0, 0.01, 0.1, 1.0, 5.0, 10.0, 50, 100.0, 250, 500, 1000] res['results'] = [] for i, interval_mw in enumerate(res['intervals']): s = get_ndp_code(interval_mw=interval_mw) ndp = parse_ndp(s, context=context) basename = ('drone_unc2_%02d_%s_mw' % (i, interval_mw)).replace('.', '_') fn = os.path.join('generated', 'drone_unc2', basename + '.mcdp') dn = os.path.dirname(fn) if not os.path.exists(dn): os.makedirs(dn) with open(fn, 'w') as f: f.write(s) print('Generated %s' % fn) result = solve_stats(ndp) result['ndp'] = ndp res['results'].append(result) return res
def check_canonical2(): # change ndp = parse_ndp(""" mcdp { A = instance catalogue { provides f1 [g] requires r1 [J] a1 | 10 g | 10 J a2 | 15 g | 15 J } B = instance catalogue { provides f2 [J] requires r2 [W] b1 | 10 J | 10 W b2 | 15 J | 15 W } provides f <= A.f1 A.r1 <= B.f2 requires r >= B.r2 } """) dp = ndp.get_dp() print(dp.repr_long()) I = dp.get_imp_space() print('I: %s' % I)
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)
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)
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)
def check_lang_namedtuple3(): parse_wrap(Syntax.rvalue_label_indexing, "capability..weight ")[0] parse_ndp(""" mcdp { provides capability [ product(weight: g, energy: J) ] capability..weight <= 1g capability..energy <= 2J } """)
def check_loop_result2(): ndp = parse_ndp(""" mcdp { s = instance mcdp { requires x [Nat] requires y [Nat] provides c [Nat] required x + required y >= provided c } requires x for s provides c using s requires y2 = y required by s * nat:2 }""" ) dp = ndp.get_dp() f = 2 res = dp.solve(f) expected = set([(0, 4), (1, 2), (2, 0)]) assert_equal(expected, res.minimals)
def check_unit_conversions(): ndp = parse_ndp(""" # test connected mcdp { requires a [m/s] provides b [m/s] sub motor = instance mcdp { provides vel [mph] requires vel2 [mph] vel2 >= vel + 1 mph } a >= motor.vel2 b <= motor.vel } """) dp = ndp.get_dp() r = dp.solve(0.0) print r limit = list(r.minimals)[0] # 1 MPH = 0.44704 m / s assert_allclose(limit, ONE_MPH_IN_M_S)
def check_conversion3(): #print("How does it work with negative numbers?") string = """ mcdp { provides f [g] requires r [g] c = -0.1 kg required r >= provided f + c }""" ndp = parse_ndp(string) # same as: # r + 0.1 kg >= f dp = ndp.get_dp() #print dp.repr_long() r = dp.solve(0.0) assert r.minimals == set([0.0]), r # one solution for 100 g r = dp.solve(100.0) assert r.minimals == set([0.0]), r r = dp.solve(200.0) assert r.minimals == set([100.0]), r
def check_spaces4(): parse_wrap_check('<5mm, 5mm, 5mm>', Syntax.tuple_of_constants) parse_wrap_check('step_up1 | {5 V} | {1.5 V} | 5 $ | 20 g | <5mm, 5mm, 5mm>', Syntax.catalogue_row) parse_ndp(""" catalogue { provides voltage [℘(V)] requires v_in [℘(V)] requires cost [$] requires mass [g] requires shape [m x m x m] step_up1 | {5 V} | {1.5 V} | 5 $ | 20 g | <5mm, 5mm, 5mm> step_up2 | {12 V} | {1.5 V} | 10 $ | 20 g | <5mm, 5mm, 5mm> step_up2 | {5 V, 12 V} | {1.5 V} | 10 $ | 20 g | <5mm, 5mm, 5mm> } """)
def check_flatten4(): ndp = parse_ndp(""" mcdp { M = instance mcdp { requires r1 [dimensionless] requires r2 [dimensionless] provides f1 [dimensionless] f1 <= r1 * r2 } N = instance mcdp { requires r1 [dimensionless] requires r2 [dimensionless] provides f1 [dimensionless] f1 <= r1 * r2 } provides M1 <= M.f1 requires R1 >= M.r1 requires R2 >= M.r2 provides NF1 <= N.f1 requires NR1 >= N.r1 requires NR2 >= N.r2 } """) ndp2 = ndp.flatten() print('resulting ndp2:\n') print ndp2
def suggestions_exponent2(): s = """ mcdp { variable a, c [dimensionless] c ≽ a^2 + 1 }""" # x = parse_wrap(Syntax.ndpt_dp_rvalue, s)[0] # xr = parse_ndp_refine(x, Context()) suggestions = get_suggestions_ndp(s) # print suggestions assert_equal(1, len(suggestions)) assert_equal('\xc2\xb2', suggestions[0][1]) s2 = apply_suggestions(s, suggestions) parse_ndp(s2)
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)
def go(): librarian = Librarian() librarian.find_libraries('../..') library = librarian.load_library('droneD_complete_templates') library.use_cache_dir('_cached/drone_unc2') context = library._generate_context_with_hooks() res = {} res['intervals'] = [ 0, 0.01, 0.1, 1.0, 5.0, 10.0, 50, 100.0, 250, 500, 1000 ] res['results'] = [] for i, interval_mw in enumerate(res['intervals']): s = get_ndp_code(interval_mw=interval_mw) ndp = parse_ndp(s, context=context) basename = ('drone_unc2_%02d_%s_mw' % (i, interval_mw)).replace( '.', '_') fn = os.path.join('generated', 'drone_unc2', basename + '.mcdp') dn = os.path.dirname(fn) if not os.path.exists(dn): os.makedirs(dn) with open(fn, 'w') as f: f.write(s) print('Generated %s' % fn) result = solve_stats(ndp) result['ndp'] = ndp res['results'].append(result) return res
def check_rcomp2(): s = """ mcdp { requires x = 1.0 } """ ndp = parse_ndp(s) assert_equal(Rcomp(), ndp.get_rtype('x'))
def check_rcomp3(): s = """ mcdp { provides x = 1.0 } """ ndp = parse_ndp(s) assert_equal(Rcomp(), ndp.get_ftype('x'))
def check_nat3(): s = """ mcdp { provides x = 1 } """ ndp = parse_ndp(s) assert_equal(Nat(), ndp.get_ftype('x'))
def check_tuples3(): _res = parse_ndp(""" mcdp { requires r [ J x g] r >= < 1J, 0g > } """)
def check_nat2(): s = """ mcdp { requires x = 1 } """ ndp = parse_ndp(s) assert_equal(Nat(), ndp.get_rtype('x'))
def test_imp_space_1(): ndp0 = parse_ndp(""" mcdp { actuation = instance mcdp { # actuators need to provide this lift provides lift [N] # and will require power requires power [W] # simple model: quadratic c = 0.002 W/N^2 power >= lift * lift * c a = instance catalogue { provides a [N] one | 10N } a.a >= 0N } requires power for actuation provides lift using actuation } """) assert isinstance(ndp0, CompositeNamedDP) ndp0_labeled = get_labelled_version(ndp0) _ndp = ndp0 dp = ndp0_labeled.get_dp() # print ndp.repr_long() # print dp.repr_long() f = 0.0 R = dp.get_res_space() ur = dp.solve(f) I = dp.get_imp_space() assert isinstance(I, SpaceProduct) print(getattr(I, ATTRIBUTE_NDP_RECURSIVE_NAME, 'no attr')) 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) print('imp dict: %r' % imp_dict) assert set(imp_dict) == set(['_res_power', '_fun_lift', 'actuation']), imp_dict found = set(imp_dict['actuation']) expected = set(['_mult1', 'a', '_res_power', '_c', '_prod1', '_fun_lift', '_join_fname1']) assert_equal(expected, found) context = {} artifact = ndp_make(ndp0, imp_dict, context) print('artifact: %s' % artifact)
def check_spaces4(): print parse_wrap_check('<5mm, 5mm, 5mm>', Syntax.tuple_of_constants) print parse_wrap_check('step_up1 | {5 V} | {1.5 V} | 5 $ | 20 g | <5mm, 5mm, 5mm>', Syntax.catalogue_row) parse_ndp(""" catalogue { provides voltage [℘(V)] requires v_in [℘(V)] requires cost [$] requires mass [g] requires shape [m x m x m] step_up1 | {5 V} | {1.5 V} | 5 $ | 20 g | <5mm, 5mm, 5mm> step_up2 | {12 V} | {1.5 V} | 10 $ | 20 g | <5mm, 5mm, 5mm> step_up2 | {5 V, 12 V} | {1.5 V} | 10 $ | 20 g | <5mm, 5mm, 5mm> } """) pass
def check_tuples3(): res = parse_ndp(""" mcdp { requires r [ J x g] r >= < 1J, 0g > } """) print(res)
def check_lang_singlespace3(): ndp1 = parse_ndp(""" mcdp { provides power [ S(electric_power) x W ] requires heat [ S(heat) x W ] efficiency = 0.9 [] r_heat = take(required heat, 1) f_power = take(provided power, 1) r_heat >= f_power / efficiency } """) ndp2 = parse_ndp(""" mcdp { provides power [ S(electric_power) x W ] requires heat [ S(heat) x W ] efficiency = 0.9 [] f_power = take(provided power, 1) heat >= <S(heat):*, f_power / efficiency> } """) dp1 = ndp1.get_dp() dp2 = ndp2.get_dp() R = dp1.get_res_space() print type(R), R UR = UpperSets(R) res1 = dp1.solve(('electric_power', 10.0)) res2 = dp2.solve(('electric_power', 10.0)) print UR.format(res1) print UR.format(res2)
def check_tuples8(): res = parse_ndp(""" mcdp { provides f [ product(a:J, b:g) ] take(provided f, a) <= 1 J take(provided f, b) <= 1 g } """) print res res = parse_ndp(""" mcdp { provides f [ product(a:J, b:g) ] (provided f).a <= 1 J (provided f).b <= 1 g } """) print res
def check_unit_conversions2(): tu = get_types_universe() A = make_rcompunit('mph') B = make_rcompunit('m/s') assert not A == B tu.check_leq(A, B) tu.check_leq(B, A) assert not tu.equal(A, B) B_from_A, A_from_B = tu.get_embedding(A, B) print('B_from_A: %s' % B_from_A) print('A_from_B: %s' % A_from_B) tu.check_equal(B_from_A.dom, A) tu.check_equal(B_from_A.cod, B) tu.check_equal(A_from_B.dom, B) tu.check_equal(A_from_B.cod, A) print('B_from_A: %s a=1.0 B_from_A(1.0) = %s' % (B_from_A, B_from_A(1.0))) assert_allclose(B_from_A(1.0), ONE_MPH_IN_M_S) assert_allclose(A_from_B(ONE_MPH_IN_M_S), 1.0) ndp = parse_ndp(""" mcdp { provides a [m/s] provides b [mph] requires c [m/s] requires d [mph] c >= a + b d >= a + b } """) print ndp.repr_long() dp = ndp.get_dp() print dp.repr_long() cases = ( ((0.0, 1.0), (ONE_MPH_IN_M_S, 1.0)), ((1.0, 0.0), (1.0, 1.0 / ONE_MPH_IN_M_S)), ) for func, expected in cases: print('func: %s F = %s' % (str(func), dp.get_fun_space())) print('expected: %s' % str(expected)) r = dp.solve(func) print('obtained: %s %s' % (str(r), dp.get_res_space())) limit = list(r.minimals)[0] assert_allclose(limit, expected)
def check_tuples7(): res = parse_ndp(""" mcdp { requires r [ product(a:J, b:g) ] take(required r, a) >= 1 J take(required r, b) >= 1 g } """) print res res = parse_ndp(""" mcdp { requires r [ product(a:J, b:g) ] (required r).a >= 1 J (required r).b >= 1 g } """) print res
def check_subtraction1(): s = """ mcdp { v1 = 10 g v2 = 2 g v3 = 1 g v = v1 - v2 - v3 requires x = v } """ parse_ndp(s) s = """ mcdp { t = instance mcdp { v1 = 10 g v2 = 2 g v3 = 1 g v = v1 - v2 - v3 requires x = v } } """ parse_ndp(s) parse_constant(""" assert_equal( solve(<>, mcdp { v1 = 10 g v2 = 2 g v3 = 1 g v = v1 - v2 - v3 requires x = v }), upperclosure { 7 g } ) """)
def check_anyof1(): ndp = parse_ndp(""" mcdp { requires x [g x g] x >= any-of({<0g,1g>, <1g, 0g>}) } """) dp = ndp.get_dp() R = dp.get_res_space() UR = UpperSets(R) res = dp.solve(()) UR.check_equal(res, UpperSet([(0.0,1.0),(1.0,0.0)], R))