def eval_rvalue_approx_step(r, context): assert isinstance(r, CDP.ApproxStepRes) resource = eval_rvalue(r.rvalue, context) step = eval_constant(r.step, context) R = context.get_rtype(resource) tu = get_types_universe() try: tu.check_leq(step.unit, R) except NotLeq: msg = ('The step is specified in a unit (%s), which is not compatible ' 'with the resource (%s).' % (step.unit, R)) raise_desc(DPSemanticError, msg) stepu = express_value_in_isomorphic_space(S1=step.unit, s1=step.value, S2=R) if not isinstance(R, (RcompUnits)): msg = 'approx() not implemented for %s.'%R raise_desc(DPNotImplementedError, msg) dp = makeLinearCeilDP(R, stepu) return create_operation(context, dp=dp, resources=[resource], name_prefix='_approx', op_prefix='_toapprox', res_prefix='_result')
def get_resource_possibly_converted(r, P, context): """ Returns a resource possibly converted to the space P """ assert isinstance(r, CResource) R = context.get_rtype(r) tu = get_types_universe() if tu.equal(R, P): return r else: try: tu.get_super_conversion(R, P) except NotLeq as e: msg = 'Cannot convert %s to %s.' % (R, P) raise_wrapped(DPSemanticError, e, msg, R=R, P=P, exc=sys.exc_info()) conversion = get_conversion(R, P) if conversion is None: return r else: r2 = create_operation(context, conversion, [r], name_prefix='_conv_grpc', op_prefix='_op', res_prefix='_res') return r2
def get_common(ua, ub): Pa = ua.P Pb = ub.P if not isinstance(Pa, PosetProduct) or not isinstance(Pb, PosetProduct): raise NotImplementedError((Pa, Pb)) # first, it might be that they have different spaces # let's find out how to match them tu = get_types_universe() # for each i in Pa, we will match it to the first matches1 = [] for i, P in enumerate(Pa.subs): for j, Q in enumerate(Pb.subs): if ('B', j) in matches1: continue if tu.leq(P, Q): matches1.append(('B', j)) break else: matches1.append(('A', i)) matches2 = [] for j, Q in enumerate(Pb.subs): if ('B', j) in matches1: # used by somebody matches2.append(('B', j)) else: for i, P in enumerate(Pa.subs): if matches1[i] is not None: continue if tu.leq(Q, P): matches2.append(('A', i)) break else: matches2.append(('B', j)) print('matches1: %s' % matches1) print('matches2: %s' % matches2) used = sorted(set(matches1 + matches2)) def get_P(_): (which, index) = _ if which == 'A': return Pa.subs[index] if which == 'B': return Pb.subs[index] assert False Ps = PosetProduct(tuple(map(get_P, used))) print('used: %s' % used) print('Ps: %s' % Ps) # now we need to complete the first Ps_a = get(matches1, used, Ps, get_P, Pa, ua) Ps_b = get(matches2, used, Ps, get_P, Pb, ub) print('Ps_a: %s' % Ps_a) print('Ps_b: %s' % Ps_b) S = UpperSets(Ps) return S, Ps_a, Ps_b
def eval_solve_r(op, context): check_isinstance(op, CDP.SolveRModel) from .eval_ndp_imp import eval_ndp ndp = eval_ndp(op.model, context) dp = ndp.get_dp() r0 = eval_constant(op.r, context) F = dp.get_fun_space() R = dp.get_res_space() tu = get_types_universe() try: tu.check_leq(r0.unit, R) except NotLeq as e: msg = 'Input not correct.' raise_wrapped(DPSemanticError, e, msg, compact=True) r = r0.cast_value(R) res = dp.solve_r(r) try: LF = LowerSets(F) return ValueWithUnits(res, LF) except NotBelongs as e: msg = 'Invalid result of solve_r().' raise_desc(DPInternalError, msg, res=res, dp=dp.repr_long())
def eval_lfunction_invplus_ops(fs, context): if len(fs) == 1: raise DPInternalError(fs) elif len(fs) > 2: # pragma: no cover mcdp_dev_warning('Maybe this should be smarter?') rest = eval_lfunction_invplus_ops(fs[1:], context) return eval_lfunction_invplus_ops([fs[0], rest], context) else: Fs = map(context.get_ftype, fs) R = Fs[0] if all(isinstance(_, RcompUnits) for _ in Fs): tu = get_types_universe() if not tu.leq(Fs[1], Fs[0]): msg = 'Inconsistent units %s and %s.' % (Fs[1], Fs[0]) raise_desc(DPSemanticError, msg, Fs0=Fs[0], Fs1=Fs[1]) if not tu.equal(Fs[1], Fs[0]): msg = 'This case was not implemented yet. Differing units %s and %s.' % (Fs[1], Fs[0]) raise_desc(DPNotImplementedError, msg, Fs0=Fs[0], Fs1=Fs[1]) dp = InvPlus2(R, tuple(Fs)) elif all(isinstance(_, Rcomp) for _ in Fs): dp = InvPlus2(R, tuple(Fs)) elif all(isinstance(_, Nat) for _ in Fs): dp = InvPlus2Nat(R, tuple(Fs)) else: # pragma: no cover msg = 'Cannot find operator for these types.' raise_desc(DPInternalError, msg, Fs=Fs) return create_operation_lf(context, dp=dp, functions=fs, name_prefix='_invplus', op_prefix='_', res_prefix='_result')
def get_function_possibly_converted(cf, P, context): """ Returns a resource possibly converted to the space P """ check_isinstance(cf, CFunction) F = context.get_ftype(cf) tu = get_types_universe() if tu.equal(F, P): return cf else: try: tu.check_leq(P, F) except NotLeq as e: msg = 'Cannot convert %s to %s.' % (P, F) raise_wrapped(DPSemanticError, e, msg,P=P, F=F) conversion = get_conversion(P, F) if conversion is None: return cf else: cf2 = create_operation_lf(context, dp=conversion, functions=[cf], name_prefix='_conv_gfpc', op_prefix='_op', res_prefix='_res') return cf2
def __init__(self, dps): check_isinstance(dps, tuple) tu = get_types_universe() F1 = dps[0].get_fun_space() R1 = dps[0].get_res_space() for dp in dps: Fj = dp.get_fun_space() Rj = dp.get_res_space() try: tu.check_equal(F1, Fj) tu.check_equal(R1, Rj) except NotEqual: msg = 'Cannot form the co-product.' raise_desc(ValueError, msg, dps=dps) F = F1 R = R1 Ms = [dp.get_imp_space() for dp in dps] self.dps = dps self.M = Coproduct1(tuple(Ms)) PrimitiveDP.__init__(self, F=F, R=R, I=self.M)
def create_operation_lf(context, dp, functions, name_prefix, op_prefix='_op', res_prefix='_res', allow_conversion=True): name = context.new_name(name_prefix) name_result = context.new_res_name(res_prefix) rnames = [] for i, f in enumerate(functions): ni = context.new_fun_name('%s%s' % (op_prefix, i)) rnames.append(ni) _rnames = rnames[0] if len(rnames) == 1 else rnames ndp = dpwrap(dp, name_result, _rnames) connections = [] tu = get_types_universe() for i, f in enumerate(functions): # source resource Fi = context.get_ftype(f) # function Fhave = ndp.get_rtype(rnames[i]) # print('------- argu %d' % i) # # print('I need to connect function %s of type %s to resource %s of new NDP with type %s'% # (f, Fi, rnames[i], Fhave)) # # print('Fi: %s' % Fi) # print('Fhave: %s' % Fhave) if not tu.equal(Fi, Fhave): if not allow_conversion: msg = ('The types are %s and %s are not equal, and ' 'allow_conversion is False' % (Fi, Fhave)) raise DPInternalError(msg) # print('creating conversion') conversion = get_conversion(Fhave, Fi) if conversion is None: msg = 'I need a conversion from %s to %s' % (Fi, Fhave) raise DPInternalError(msg) else: # print('Conversion: %s' % conversion.repr_long()) # print('Creating recursive...') f = create_operation_lf(context, conversion, [f], name_prefix='_conversion_for_%s' % name_result, allow_conversion=False) c = Connection(dp2=f.dp, s2=f.s, dp1=name, s1=rnames[i]) connections.append(c) context.add_ndp(name, ndp) for c in connections: context.add_connection(c) res = context.make_function(name, name_result) return res
def convert_string_query(ndp, query, context): """ Converts a string query to a value that can be passed to the DP. Example: f = bind(ndp, dict(power='100mW')) f == 0.1 dp.solve(f) """ # first: make sure the names are the same fnames = ndp.get_fnames() fnames2 = set(query) if set(fnames) != fnames2: msg = 'Missing values in query or too many values.' raise_desc(ValueError, msg, fnames=fnames, query=query) fds = [] Fds = [] tu = get_types_universe() for fname in fnames: q = query[fname] vu = parse_constant(q, context) fds.append(vu.value) Fds.append(vu.unit) F0 = ndp.get_ftype(fname) if not tu.leq(vu.unit, F0): msg = 'Invalid value for %r: %s does not cast to %s.' % (fname, vu, F0) raise_desc(ValueError, msg) Fd = PosetProduct(tuple(Fds)) fd = tuple(fds) if len(fnames) == 1: Fd = Fd[0] fd = fd[0] else: Fd = Fd fd = fd F = ndp.get_ftypes(fnames) if len(fnames) == 1: F = F[0] tu.check_leq(Fd, F) A_to_B, _ = tu.get_embedding(Fd, F) fg = A_to_B(fd) #print('Fd: %s' % Fd.format(fd)) #print('F: %s' % F.format(fg)) return fg
def eval_PlusN_ops_multi(resources, context): resources_types = [context.get_rtype(_) for _ in resources] target_int = Int() tu = get_types_universe() def castable_to_int(_): return tu.leq(_, target_int) def exactly_Rcomp_or_Nat(x): return exactly_Rcomp(x) or isinstance(x, Nat) def exactly_Rcomp(x): return isinstance(x, Rcomp) if all(exactly_Rcomp(_) for _ in resources_types): n = len(resources_types) dp = SumNRcompDP(n) elif all(isinstance(_, RcompUnits) for _ in resources_types): # addition between floats R = resources_types[0] Fs = tuple(resources_types) try: sum_dimensionality_works(Fs, R) except ValueError: msg = '' for r, rt in zip(resources, resources_types): msg += '- %s has type %s\n' % (r, rt) raise_desc(DPSemanticError, 'Incompatible units:\n%s' % msg) dp = SumNDP(Fs, R) elif all(isinstance(_, Nat) for _ in resources_types): # natural number dp = SumNNatDP(len(resources)) elif all(castable_to_int(_) for _ in resources_types): # XXX cast dp = SumNIntDP(len(resources)) elif all(exactly_Rcomp_or_Nat(_) for _ in resources_types): resources = [ get_resource_possibly_converted(_, Rcomp(), context) for _ in resources ] dp = SumNRcompDP(len(resources)) else: msg = 'Cannot find sum operator for combination of types.' raise_desc(DPNotImplementedError, msg, resources_types=resources_types) r = create_operation(context, dp, resources, name_prefix='_sum', op_prefix='_term', res_prefix='_result') return r
def get_providers_for_type(self, R): options = [] tu = get_types_universe() for id_ndp in self.options: ndp = self.load_ndp(id_ndp) fnames = ndp.get_fnames() ftypes = ndp.get_ftypes(fnames) for fname, F in zip(fnames, ftypes): if tu.leq(R, F): options.append((id_ndp, fname)) mcdp_dev_warning("assume that it is symmetric") break return options
def check_plot_space(self, space): tu = get_types_universe() if not (isinstance(space, PosetProduct) and len(space.subs) == 2): msg = 'I can only plot 2-tuples of upper sets.' raise_desc(NotPlottable, msg, space=space) tu.check_equal(space[0], space[1]) try: self.p.check_plot_space(space[0]) except NotPlottable as e: msg = 'It is a 2-tuple, but cannot plot inside. ' raise_wrapped(NotPlottable, e, msg, compact=True)
def check_coproduct_embedding2(): """ A + B == A + B """ A = FinitePoset(set(['a1', 'a2', 'a3']), []) B = FinitePoset(set(['b1', 'b2']), []) P1 = PosetCoproduct((A, B)) P2 = PosetCoproduct((A, B)) tu = get_types_universe() tu.check_equal(P1, P2) tu.check_leq(P1, P2) tu.check_leq(P2, P1)
def interpret_params_1string(p, F, context=None): if context is None: context = Context() res = parse_wrap(Syntax.constant_value, p)[0] vu = eval_constant(res, context) Fd = vu.unit fd = vu.value tu = get_types_universe() tu.check_leq(Fd, F) A_to_B, _ = tu.get_embedding(Fd, F) fg = A_to_B(fd) return fg
def __init__(self, F, Rs): for _ in Rs: check_isinstance(_, (Rcomp, RcompUnits)) check_isinstance(F, (Rcomp, RcompUnits)) self.Rs = Rs R = PosetProduct(Rs) tu = get_types_universe() if not tu.equal(Rs[0], Rs[1]) or not tu.equal(F, Rs[0]): msg = 'InvPlus only available for consistent units.' raise_desc(DPInternalError, msg, F=F, Rs=Rs) M = PosetProduct((F, R)) PrimitiveDP.__init__(self, F=F, R=R, I=M)
def __init__(self, Fs, R): dom = PosetProduct(Fs) cod = R Map.__init__(self, dom=dom, cod=cod) tu = get_types_universe() self.subs = [] target = Int() for F in Fs: # need F to be cast to Int F_to_Int, _ = tu.get_embedding(F, target) self.subs.append(F_to_Int) self.to_R, _ = tu.get_embedding(target, R)
def check_coproduct_embedding3(): """ A + B != B + A, but A + B ~= B + A """ A = FinitePoset(set(['a1', 'a2', 'a3']), []) B = FinitePoset(set(['b1', 'b2']), []) P1 = PosetCoproduct((A, B)) P2 = PosetCoproduct((B, A)) tu = get_types_universe() tu.check_leq(P1, P2) tu.check_leq(P2, P1) A_to_B1, B_to_A1 = tu.get_embedding(A, B) # @UnusedVariable B_to_A2, A_to_B2 = tu.get_embedding(B, A) # @UnusedVariable
def get_conversion(A, B): """ Returns None if there is no need for a Conversion Map. Otherwise returns a Conversion (< WrapAMap). """ tu = get_types_universe() if tu.equal(A, B): conversion = None else: try: A_to_B, B_to_A = tu.get_super_conversion(A, B) mcdp_dev_warning('not really sure of the semantics of this') conversion = Conversion(A_to_B, B_to_A) except NotLeq: raise return conversion
def eval_PlusN_ops_multi(resources, context): resources_types = [context.get_rtype(_) for _ in resources] target_int = Int() tu = get_types_universe() def castable_to_int(_): return tu.leq(_, target_int) def exactly_Rcomp_or_Nat(x): return exactly_Rcomp(x) or isinstance(x, Nat) def exactly_Rcomp(x): return isinstance(x, Rcomp) if all(exactly_Rcomp(_) for _ in resources_types): n = len(resources_types) dp = SumNRcompDP(n) elif all(isinstance(_, RcompUnits) for _ in resources_types): # addition between floats R = resources_types[0] Fs = tuple(resources_types) try: sum_dimensionality_works(Fs, R) except ValueError: msg = '' for r, rt in zip(resources, resources_types): msg += '- %s has type %s\n' % (r, rt) raise_desc(DPSemanticError, 'Incompatible units:\n%s' % msg) dp = SumNDP(Fs, R) elif all(isinstance(_, Nat) for _ in resources_types): # natural number dp = SumNNatDP(len(resources)) elif all(castable_to_int(_) for _ in resources_types): # XXX cast dp = SumNIntDP(len(resources)) elif all(exactly_Rcomp_or_Nat(_) for _ in resources_types): resources = [get_resource_possibly_converted(_, Rcomp(), context) for _ in resources] dp = SumNRcompDP(len(resources)) else: msg = 'Cannot find sum operator for combination of types.' raise_desc(DPInternalError, msg, resources_types=resources_types) r = create_operation(context, dp, resources, name_prefix='_sum', op_prefix='_term', res_prefix='_result') return r
def adv_embed_1(): """ PosetProduct does not take into account permutations. """ P1 = parse_poset('m x J') P2 = parse_poset('J x m') tu = get_types_universe() try: tu.check_leq(P1, P2) except NotLeq: pass else: assert False try: tu.check_leq(P2, P1) except NotLeq: pass else: assert False
def __init__(self, opt, options, context, executed, forbidden, lower_bounds, ur, creation_order): print('CREATED %s' % creation_order) self.opt = opt self.options = options self.context = context self.executed = executed self.forbidden = forbidden self.lower_bounds = lower_bounds self.ur = ur if do_extra_checks(): tu = get_types_universe() # We expect that for each unconnected resource, we have a lower bound _unconnected_fun, unconnected_res = get_missing_connections( self.context) for dp, s in unconnected_res: r = CResource(dp, s) if not r in lower_bounds: msg = 'There is no lower bound for this resource.' raise_desc(ValueError, msg, r=r, lower_bounds=lower_bounds) r_ur = lower_bounds[r] R = self.context.get_rtype(r) tu.check_equal(r_ur.P, R) # make sure we don't have extra for r in lower_bounds: assert isinstance(r, CResource), r R = self.context.get_rtype(r) assert (r.dp, r.s) in unconnected_res, (r, unconnected_res) self.num_connection_options = self._compute_connection_options() self.hash = self._compute_hash() self._msg = "" for r, lb in lower_bounds.items(): R = self.context.get_rtype(r) self.info('lb %s >= %s' % (r, lb), quiet=True) self.num_resources_need_connecting = self.compute_num_resources_need_connecting( ) self.creation_order = creation_order
def adv_embed_1(): """ PosetProduct does not take into account permutations. """ P1 = parse_poset("m x J") P2 = parse_poset("J x m") tu = get_types_universe() try: tu.check_leq(P1, P2) except NotLeq: pass else: assert False try: tu.check_leq(P2, P1) except NotLeq: pass else: assert False
def get_conversion(A, B): """ Returns None if there is no need for a Conversion Map. Otherwise returns a Conversion (< WrapAMap). """ tu = get_types_universe() if tu.equal(A, B): conversion = None else: try: A_to_B, B_to_A = tu.get_super_conversion(A, B) mcdp_dev_warning('not really sure of the semantics of this') conversion = Conversion(A_to_B, B_to_A) except NotLeq as e: raise # msg = 'Wrapping with incompatible units.' # raise_wrapped(DPSemanticError, e, msg, A=A, B=B) return conversion
def check_plot_space(self, space): tu = get_types_universe() if not isinstance(space, UpperSets): msg = 'I can only plot upper sets of R.' raise_desc(NotPlottable, msg, space=space) R = Rcomp() P = space.P if isinstance(P, RcompBase): self.P_to_S = lambda x: x else: try: tu.check_leq(P, R) except NotLeq as e: msg = ('cannot convert to R^2 from %s' % space) raise_wrapped(NotPlottable, e, msg, compact=True) self.P_to_S, _ = tu.get_embedding(P, R)
def check_plot_space(self, space): tu = get_types_universe() if not isinstance(space, UpperSets): msg = "I can only plot upper sets of R." raise_desc(NotPlottable, msg, space=space) R = Rcomp() P = space.P if isinstance(P, RcompBase): self.P_to_S = lambda x: x else: try: tu.check_leq(P, R) except NotLeq as e: msg = "cannot convert to R^2 from %s" % space raise_wrapped(NotPlottable, e, msg, compact=True) self.P_to_S, _ = tu.get_embedding(P, R)
def __init__(self, opt, options, context, executed, forbidden, lower_bounds, ur, creation_order): print('CREATED %s' % creation_order) self.opt = opt self.options = options self.context = context self.executed = executed self.forbidden = forbidden self.lower_bounds = lower_bounds self.ur = ur if do_extra_checks(): tu = get_types_universe() # We expect that for each unconnected resource, we have a lower bound _unconnected_fun, unconnected_res = get_missing_connections(self.context) for dp, s in unconnected_res: r = CResource(dp, s) if not r in lower_bounds: msg = 'There is no lower bound for this resource.' raise_desc(ValueError, msg, r=r, lower_bounds=lower_bounds) r_ur = lower_bounds[r] R = self.context.get_rtype(r) tu.check_equal(r_ur.P, R) # make sure we don't have extra for r in lower_bounds: assert isinstance(r, CResource), r R = self.context.get_rtype(r) assert (r.dp, r.s) in unconnected_res, (r, unconnected_res) self.num_connection_options = self._compute_connection_options() self.hash = self._compute_hash() self._msg = "" for r, lb in lower_bounds.items(): R = self.context.get_rtype(r) self.info('lb %s >= %s' % (r, lb), quiet=True) self.num_resources_need_connecting = self.compute_num_resources_need_connecting() self.creation_order = creation_order
def eval_rvalue_approx_u(r, context): assert isinstance(r, CDP.ApproxURes) # # r1-approx-r2----------------- Uncertainty gate # |____(+ step)--[r3]| r1 = eval_rvalue(r.rvalue, context) step = eval_constant(r.step, context) R = context.get_rtype(r1) tu = get_types_universe() try: tu.check_leq(step.unit, R) except NotLeq as e: msg = ('The step is specified in a unit (%s), which is not compatible ' 'with the resource (%s).' % (step.unit, R)) raise_wrapped(DPSemanticError, e, msg, compact=True) stepu = step.cast_value(R) if stepu == 0.0: return r1 dp = makeLinearFloor0DP(R, stepu) r2 = create_operation(context, dp=dp, resources=[r1], name_prefix='_approx', op_prefix='_toapprox', res_prefix='_result') dpsum = PlusValueDP(R, c_value=step.value, c_space=step.unit) r3 = create_operation(context, dp=dpsum, resources=[r2], name_prefix='_sum') dpu = UncertainGate(R) return create_operation(context, dp=dpu, resources=[r2, r3], name_prefix='_uncertain')
def less_resources2(ua, ub): """ ua must be <= ub """ Pa = ua.P Pb = ub.P if not isinstance(Pa, PosetProduct) or not isinstance(Pb, PosetProduct): raise NotImplementedError((Pa, Pb)) tu = get_types_universe() matches = [] for i, P in enumerate(Pa.subs): for j, Q in enumerate(Pb.subs): if j in matches: continue if tu.leq(P, Q): matches.append(j) break else: # msg = 'Could not find match.' return False # now we have found an embedding # first we create a projection for Pb m1 = MuxMap(F=Pb, coords=matches) ub2 = upperset_project_map(ub, m1) Pb2 = ub2.P UPb2 = UpperSets(Pb2) # now we create the embedding A_to_B, _ = tu.get_embedding(Pa, Pb2) ua2 = upperset_project_map(ua, A_to_B) print('Pa: %s' % Pa) print('Pb2: %s' % Pb2) print('ua2: %s' % ua2) print('ub2: %s' % ub2) return UPb2.leq(ua2, ub2)
def eval_solve_f(op, context): check_isinstance(op, CDP.SolveModel) from .eval_ndp_imp import eval_ndp ndp = eval_ndp(op.model, context) dp = ndp.get_dp() f0 = eval_constant(op.f, context) F = dp.get_fun_space() R = dp.get_res_space() tu = get_types_universe() try: tu.check_leq(f0.unit, F) except NotLeq as e: msg = 'Input not correct.' raise_wrapped(DPSemanticError, e, msg, compact=True) f = f0.cast_value(F) res = dp.solve(f) UR = UpperSets(R) return ValueWithUnits(res, UR)
def check_plot_space(self, space): tu = get_types_universe() if not isinstance(space, UpperSets): msg = 'I can only plot upper sets.' raise_desc(NotPlottable, msg, space=space) P = space.P if isinstance(P, PosetProduct) and len(P) == 2 and \ isinstance(P[0], PosetProduct) and len(P[0]) == 2: self.P_to_S = lambda x: x else: try: tu.check_leq(P, self.S) except NotLeq as e: msg = ('cannot convert from %s to %s' % (P, self.S)) raise_wrapped(NotPlottable, e, msg, compact=True) self.P_to_S, _f2 = tu.get_embedding(P, self.S)
def check_same_interface(interface, ndp): """ Raises DifferentInterface """ fi = set(interface.get_fnames()) ri = set(interface.get_rnames()) fn = set(ndp.get_fnames()) rn = set(ndp.get_rnames()) extra_functions = fn - fi extra_resources = rn - ri missing_functions = fi - fn missing_resources = ri - rn problems = (extra_functions or extra_resources or missing_functions or missing_resources) if problems: msg = 'Different number of functions and resources.' raise_desc(DifferentInterface, msg) tu = get_types_universe() for f in ndp.get_fnames(): F1 = ndp.get_ftype(f) F2 = interface.get_ftype(f) try: tu.check_leq(F1, F2) except NotLeq as e: msg = 'A port is not compatible.' raise_desc(DPSemanticError, e, msg, f=f, F1=F1, F2=F2) for r in ndp.get_rnames(): R1 = ndp.get_rtype(r) R2 = interface.get_rtype(r) try: tu.check_leq(R1, R2) except NotLeq as e: msg = 'A port is not compatible.' raise_desc(DPSemanticError, e, msg, r=r, R1=R1, R2=R2)
def check_plot_space(self, space): tu = get_types_universe() if not isinstance(space, UpperSets): msg = 'I can only plot upper sets of something isomorphic to R2.' raise_desc(NotPlottable, msg, space=space) P = space.P self.R2 = PosetProduct((Rcomp(), Rcomp())) if isinstance(space.P, PosetProduct) and len(space.P) == 2 and \ isinstance(space.P[0], RcompUnits) and isinstance(space.P[1], RcompUnits): self.P_to_S = lambda x: x else: #logger.debug('space = %s ; P = %s; R2 = %s' % (space,space.P,R2)) try: tu.check_leq(P, self.R2) except NotLeq as e: msg = ('cannot convert to R^2 from %s' % space) raise_wrapped(NotPlottable, e, msg, compact=True) self.P_to_S, _f2 = tu.get_embedding(P, self.R2)
def get_compatible_unconnected_functions(R, context, unconnected_fun, only_one_per_dp=True): tu = get_types_universe() res = [] used_dps = set() for dp1, fname in unconnected_fun: # skip if we already used it # TODO: maybe only allow this for numbered options? if only_one_per_dp: if dp1 in used_dps: continue f = CFunction(dp1, fname) F = context.get_ftype(f) if tu.leq(R, F): res.append(f) used_dps.add(dp1) # print('get_compatible_unconnected_functions(): %s -> %s ' % (R, res)) return res
def __init__(self, dp1): self.dp1 = dp1 F0 = self.dp1.get_fun_space() R0 = self.dp1.get_res_space() I0 = self.dp1.get_imp_space() if not isinstance(F0, PosetProduct) or len(F0.subs) != 2: msg = 'The function space must be a product of length 2.' raise_desc(ValueError, msg, F0=F0) if not isinstance(R0, PosetProduct) or len(R0.subs) != 2: msg = 'The resource space must be a product of length 2.' raise_desc(ValueError, msg, R0=R0) F1, F2 = F0[0], F0[1] R1, R2 = R0[0], R0[1] tu = get_types_universe() try: tu.check_equal(F2, R2) except NotEqual as e: msg = ('The second component of function and resource space ' 'must be equal.') raise_wrapped(ValueError, e, msg, F2=F2, R2=R2) F = F1 R = R1 from mcdp_dp.dp_series import get_product_compact M, _, _ = get_product_compact(I0, F2, R2) self.M0 = I0 self.F1 = F1 self.F2 = F2 self.R1 = R1 self.R2 = R2 self._solve_cache = {} PrimitiveDP.__init__(self, F=F, R=R, I=M)
def add_constraint(context, resource, function): check_isinstance(resource, CResource) check_isinstance(function, CFunction) R1 = context.get_rtype(resource) F2 = context.get_ftype(function) tu = get_types_universe() try: if tu.equal(R1, F2): c = Connection(dp1=resource.dp, s1=resource.s, dp2=function.dp, s2=function.s) context.add_connection(c) else: # F2 ---- (<=) ---- becomes ----(<=)--- [R1_to_F2] ---- # | R1 F2 R1 R1 F2 # R1 try: R1_to_F2, F2_to_R1 = tu.get_super_conversion(R1, F2) conversion = Conversion(R1_to_F2, F2_to_R1) assert tu.equal(R1, conversion.get_fun_space()) assert tu.equal(F2, conversion.get_res_space()) resource2 = create_operation(context=context, dp=conversion, resources=[resource], name_prefix='_conversion') c = Connection(dp1=resource2.dp, s1=resource2.s, dp2=function.dp, s2=function.s) context.add_connection(c) except NotLeq as e: msg = 'Constraint between incompatible spaces.' msg += '\n %s can be embedded in %s: %s ' % ( R1, F2, tu.leq(R1, F2)) msg += '\n %s can be embedded in %s: %s ' % ( F2, R1, tu.leq(F2, R1)) raise_wrapped( DPSemanticError, e, msg, R1=R1, F2=F2, compact=True) except NotImplementedError as e: # pragma: no cover msg = 'Problem while creating embedding.' raise_wrapped(DPInternalError, e, msg, resource=resource, function=function, R1=R1, F2=F2)
def assert_generic(r, context, which): """ a : v1 < v2 b : v1 = v2 b : v1 = v2 """ from .eval_constant_imp import eval_constant v1 = eval_constant(r.v1, context) v2 = eval_constant(r.v2, context) # put v2 in v1's space P = v1.unit value1 = v1.value tu = get_types_universe() try: tu.check_leq(v2.unit, v1.unit) except NotLeq as e: msg = 'Cannot cast %s to %s.' % (v2.unit, v1.unit) raise_wrapped(DPSemanticError, e, msg, compact=True) value2 = express_value_in_isomorphic_space(v2.unit, v2.value, v1.unit) t = {} t['equal'] = P.equal(value1, value2) t['leq'] = P.leq(value1, value2) t['geq'] = P.leq(value2, value1) t['lt'] = t['leq'] and not t['equal'] t['gt'] = t['geq'] and not t['equal'] if not which in t: raise ValueError(t) result = t[which] if result: return passed_value() else: # assertion msg = 'Assertion %r failed.' % which raise_desc(DPUserAssertion, msg, expected=v1, obtained=v2)
def eval_lfunction_invplus_ops(fs, context): if len(fs) == 1: raise DPInternalError(fs) elif len(fs) > 2: # pragma: no cover mcdp_dev_warning('Maybe this should be smarter?') rest = eval_lfunction_invplus_ops(fs[1:], context) return eval_lfunction_invplus_ops([fs[0], rest], context) else: Fs = map(context.get_ftype, fs) R = Fs[0] if all(isinstance(_, RcompUnits) for _ in Fs): tu = get_types_universe() if not tu.leq(Fs[1], Fs[0]): msg = 'Inconsistent units %s and %s.' % (Fs[1], Fs[0]) raise_desc(DPSemanticError, msg, Fs0=Fs[0], Fs1=Fs[1]) if not tu.equal(Fs[1], Fs[0]): msg = 'This case was not implemented yet. Differing units %s and %s.' % ( Fs[1], Fs[0]) raise_desc(DPNotImplementedError, msg, Fs0=Fs[0], Fs1=Fs[1]) dp = InvPlus2(R, tuple(Fs)) elif all(isinstance(_, Rcomp) for _ in Fs): dp = InvPlus2(R, tuple(Fs)) elif all(isinstance(_, Nat) for _ in Fs): dp = InvPlus2Nat(R, tuple(Fs)) else: # pragma: no cover msg = 'Cannot find operator for these types.' raise_desc(DPInternalError, msg, Fs=Fs) return create_operation_lf(context, dp=dp, functions=fs, name_prefix='_invplus', op_prefix='_', res_prefix='_result')
def check_mult_mixed2(): tu = get_types_universe() dimensionless = parse_poset('dimensionless') Nat = parse_poset('Nat') # m * s ndp = parse_ndp(""" mcdp { provides a [m] provides b [s] requires x = provided a * provided b } """) M = ndp.get_rtype('x') tu.check_equal(M, parse_poset('m*s')) # Nat * Nat ndp = parse_ndp(""" mcdp { provides a [Nat] provides b [Nat] requires x = provided a * provided b } """) M = ndp.get_rtype('x') tu.check_equal(M, Nat) # Nat * [] ndp = parse_ndp(""" mcdp { provides a [Nat] provides b [dimensionless] requires x = provided a * provided b } """) M = ndp.get_rtype('x') tu.check_equal(M, dimensionless)
def add_constraint(context, resource, function): check_isinstance(resource, CResource) check_isinstance(function, CFunction) R1 = context.get_rtype(resource) F2 = context.get_ftype(function) tu = get_types_universe() try: if tu.equal(R1, F2): c = Connection(dp1=resource.dp, s1=resource.s, dp2=function.dp, s2=function.s) context.add_connection(c) else: ## F2 ---- (<=) ---- becomes ----(<=)--- [R1_to_F2] ---- ## | R1 F2 R1 R1 F2 ## R1 try: R1_to_F2, F2_to_R1 = tu.get_super_conversion(R1, F2) conversion = Conversion(R1_to_F2, F2_to_R1) assert tu.equal(R1, conversion.get_fun_space()) assert tu.equal(F2, conversion.get_res_space()) resource2 = create_operation(context=context, dp=conversion, resources=[resource], name_prefix='_conversion') c = Connection(dp1=resource2.dp, s1=resource2.s, dp2=function.dp, s2=function.s) context.add_connection(c) except NotLeq as e: msg = 'Constraint between incompatible spaces.' msg += '\n %s can be embedded in %s: %s ' % (R1, F2, tu.leq(R1, F2)) msg += '\n %s can be embedded in %s: %s ' % (F2, R1, tu.leq(F2, R1)) raise_wrapped(DPSemanticError, e, msg, R1=R1, F2=F2, compact=True) except NotImplementedError as e: # pragma: no cover msg = 'Problem while creating embedding.' raise_wrapped(DPInternalError, e, msg, resource=resource, function=function, R1=R1, F2=F2)
def get_resource_possibly_converted(r, P, context): """ Returns a resource possibly converted to the space P """ assert isinstance(r, CResource) R = context.get_rtype(r) tu = get_types_universe() if tu.equal(R, P): return r else: try: tu.check_leq(R, P) except NotLeq as e: msg = 'Cannot convert %s to %s.' % (R, P) raise_wrapped(DPSemanticError, e, msg, R=R, P=P) conversion = get_conversion(R, P) if conversion is None: return r else: r2 = create_operation(context, conversion, [r], name_prefix='_conv_grpc', op_prefix='_op', res_prefix='_res') return r2
def eval_ndp_catalogue(r, context): check_isinstance(r, CDP.FromCatalogue) # FIXME:need to check for re-ordering statements = unwrap_list(r.funres) fun = [x for x in statements if isinstance(x, CDP.FunStatement)] res = [x for x in statements if isinstance(x, CDP.ResStatement)] Fs = [eval_space(_.unit, context) for _ in fun] Rs = [eval_space(_.unit, context) for _ in res] assert len(fun) + len(res) == len(statements), statements tu = get_types_universe() table = r.table rows = unwrap_list(table.rows) entries = [] for row in rows: items = unwrap_list(row) name = items[0].value expected = 1 + len(fun) + len(res) if len(items) != expected: msg = 'Row with %d elements does not match expected of elements (%s fun, %s res)' % (len(items), len(fun), len(res)) # msg += ' items: %s' % str(items) raise DPSemanticError(msg, where=items[-1].where) fvalues0 = items[1:1 + len(fun)] rvalues0 = items[1 + len(fun):1 + len(fun) + len(res)] fvalues = [eval_constant(_, context) for _ in fvalues0] rvalues = [eval_constant(_, context) for _ in rvalues0] for cell, Fhave, F in zip(fvalues0, fvalues, Fs): try: tu.check_leq(Fhave.unit, F) except NotLeq as e: msg = 'Dimensionality problem: cannot convert %s to %s.' % (Fhave.unit, F) ex = lambda msg: DPSemanticError(msg, where=cell.where) raise_wrapped(ex, e, msg, compact=True) for cell, Rhave, R in zip(rvalues0, rvalues, Rs): try: tu.check_leq(Rhave.unit, R) except NotLeq as e: msg = 'Dimensionality problem: cannot convert %s to %s.' % (Rhave.unit, R) ex = lambda msg: DPSemanticError(msg, where=cell.where) raise_wrapped(ex, e, msg, compact=True) fvalues_ = [_.cast_value(F) for (_, F) in zip(fvalues, Fs)] rvalues_ = [_.cast_value(R)for (_, R) in zip(rvalues, Rs)] assert len(fvalues_) == len(fun) assert len(rvalues_) == len(res) entries.append((name, tuple(fvalues_), tuple(rvalues_))) names = set([name for (name, _, _) in entries]) M = FiniteCollectionAsSpace(names) # use integers # entries = [(float(i), b, c) for i, (_, b, c) in enumerate(entries)] fnames = [_.fname.value for _ in fun] rnames = [_.rname.value for _ in res] if len(Fs) == 1: F = Fs[0] fnames = fnames[0] entries = [(a, b[0], c) for (a, b, c) in entries] else: F = PosetProduct(tuple(Fs)) if len(Rs) == 1: R = Rs[0] rnames = rnames[0] entries = [(a, b, c[0]) for (a, b, c) in entries] else: R = PosetProduct(tuple(Rs)) dp = CatalogueDP(F=F, R=R, I=M, entries=tuple(entries)) ndp = dpwrap(dp, fnames=fnames, rnames=rnames) return ndp
def eval_ndp_dpwrap(r, context): tu = get_types_universe() statements = unwrap_list(r.statements) fun = [x for x in statements if isinstance(x, CDP.FunStatement)] res = [x for x in statements if isinstance(x, CDP.ResStatement)] assert len(fun) + len(res) == len(statements), statements impl = r.impl from .eval_primitivedp_imp import eval_primitivedp dp = eval_primitivedp(impl, context) fnames = [f.fname.value for f in fun] rnames = [r.rname.value for r in res] if len(fnames) == 1: use_fnames = fnames[0] else: use_fnames = fnames if len(rnames) == 1: use_rnames = rnames[0] else: use_rnames = rnames dp_F = dp.get_fun_space() dp_R = dp.get_res_space() # Check that the functions are the same want_Fs = tuple([eval_space(f.unit, context) for f in fun]) if len(want_Fs) == 1: want_F = want_Fs[0] else: want_F = PosetProduct(want_Fs) want_Rs = tuple([eval_space(r.unit, context) for r in res]) if len(want_Rs) == 1: want_R = want_Rs[0] else: want_R = PosetProduct(want_Rs) mcdp_dev_warning('Not sure about this') dp_prefix = get_conversion(want_F, dp_F) dp_postfix = get_conversion(dp_R, want_R) if dp_prefix is not None: dp = make_series(dp_prefix, dp) if dp_postfix is not None: dp = make_series(dp, dp_postfix) try: w = SimpleWrap(dp=dp, fnames=use_fnames, rnames=use_rnames) except ValueError as e: raise DPSemanticError(str(e), r.where) ftypes = w.get_ftypes(fnames) rtypes = w.get_rtypes(rnames) ftypes_expected = PosetProduct(tuple([eval_space(f.unit, context) for f in fun])) rtypes_expected = PosetProduct(tuple([eval_space(r.unit, context) for r in res])) try: tu.check_equal(ftypes, ftypes_expected) tu.check_equal(rtypes, rtypes_expected) except NotEqual as e: msg = 'The types in the description do not match.' raise_wrapped(DPSemanticError, e, msg, dp=dp, ftypes=ftypes, ftypes_expected=ftypes_expected, rtypes=rtypes, rtypes_expected=rtypes_expected, compact=True) return w