def generic_mult_constantsN(seq): """ Multiplies a sequence of constants that could be either Nat, Rcomp, or RCompUnits """ for c in seq: if isinstance(c.unit, RbicompUnits): assert c.value < 0 msg = 'Cannot multiply by negative number %s.' % c raise_desc(DPSemanticError, msg) posets = [_.unit for _ in seq] for p in posets: check_isinstance(p, (Nat, Rcomp, RcompUnits)) promoted, R = generic_mult_table(posets) if isinstance(R, Nat): values = [_.value for _ in seq] from functools import reduce res = reduce(Nat_mult_uppersets_continuous, values) return ValueWithUnits(res, R) else: res = 1.0 for vu, F2 in zip(seq, promoted): value2 = express_value_in_isomorphic_space(vu.unit, vu.value, F2) if F2.equal(value2, F2.get_top()): res = R.get_top() break res *= value2 return ValueWithUnits(res, R) # XXX needs to check overflow return res
def get_uncertainconstant_as_resource(v, context): warnings.warn('This is a bit inefficient') from mcdp_dp.dp_uncertain import UncertainGate vlower = ValueWithUnits(unit=v.space, value=v.lower) vupper = ValueWithUnits(unit=v.space, value=v.upper) rl = get_valuewithunits_as_resource(vlower, context) ru = get_valuewithunits_as_resource(vupper, context) dp = UncertainGate(v.space) return create_operation(context, dp=dp, resources=[rl, ru])
def eval_constant_SpecialConstant(r, context): # @UnusedVariable check_isinstance(r, CDP.SpecialConstant) constants = { 'pi': ValueWithUnits(math.pi, Rcomp()), 'e': ValueWithUnits(math.pi, Rcomp()), } constants['π'] = constants['pi'] if not r.constant_name in constants: msg = 'Could not find constant "%s".' % (r.constant_name) raise_desc(DPInternalError, msg) return constants[r.constant_name]
def x_minus_constants(x, constants): R0 = x.unit if not isinstance(R0, RcompUnits): msg = 'Cannot evaluate "-" on this space.' raise_desc(DPSemanticError, msg, R0=R0) Rb = RbicompUnits.from_rcompunits(R0) # convert each factor to R0 try: v0 = x.value for c in constants: vi = express_value_in_isomorphic_space(c.unit, c.value, Rb) v0 = RbicompUnits_subtract(Rb, v0, vi) except TypeError as e: msg = 'Failure to compute subtraction.' raise_wrapped(DPInternalError, e, msg, x=x, constants=constants) if Rb.leq(0.0, v0): R1 = R0 else: R1 = Rb return ValueWithUnits(unit=R1, value=v0)
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 reduce_constants(self, vus): S = vus[0].unit res = vus[0].value for _ in vus[1:]: v = _.cast_value(S) res = S.meet(res, v) return ValueWithUnits(res, S)
def vu_rcomp_mult_constants2(a, b): """ Multiplies two ValueWithUnits that are also RcompUnits """ check_isinstance(a.unit, RcompUnits) check_isinstance(b.unit, RcompUnits) R = mult_table(a.unit, b.unit) value = a.value * b.value return ValueWithUnits(value=value, unit=R)
def eval_constant_Minimals(op, context): from .eval_space_imp import eval_space # @Reimport space = eval_space(op.space, context) elements = space.get_minimal_elements() v = FiniteCollection(elements=elements, S=space) S = FiniteCollectionsInclusion(space) return ValueWithUnits(unit=S, value=v)
def eval_constant_SimpleValue(op, context): from .eval_space_imp import eval_space # @Reimport F = eval_space(op.space, context) assert isinstance(F, Space), op assert isinstance(F, RcompUnits) v = op.value.value # promote integer to float if isinstance(v, int) and isinstance(F, (Rcomp, RcompUnits)): v = float(v) if v < 0: if isinstance(F, RcompUnits): F = RbicompUnits(F.units, F.string) else: msg = 'Negative %s not implemented yet.' % F raise_desc(NotImplementedError, msg, F=F) try: F.belongs(v) except NotBelongs as e: msg = 'Not in space' raise_wrapped(DPSemanticError, e, msg, F=F, v=v, op=op) return ValueWithUnits(unit=F, value=v)
def eval_EmptySet(op, context): check_isinstance(op, CDP.EmptySet) from .eval_space_imp import eval_space space = eval_space(op.space, context) P = FiniteCollectionsInclusion(space) value = FiniteCollection(set([]), space) return ValueWithUnits(unit=P, value=value)
def eval_constant_MakeTuple(op, context): ops = get_odd_ops(unwrap_list(op.ops)) constants = [eval_constant(_, context) for _ in ops] # TODO: generic product Fs = [_.unit for _ in constants] vs = [_.value for _ in constants] F = PosetProduct(tuple(Fs)) v = tuple(vs) F.belongs(v) return ValueWithUnits(v, F)
def eval_constant_lowersetfromcollection(op, context): x = eval_constant(op.value, context) v = x.value u = x.unit S = u.S maximals = poset_minima(v.elements, S.leq) value = LowerSet(maximals, S) unit = LowerSets(S) if do_extra_checks(): unit.belongs(value) vu = ValueWithUnits(value, unit) return vu
def inv_constant(a): if a.unit == Nat(): raise DPNotImplementedError('division by natural number') warnings.warn('Please think more about this. Now 1/N -> 1.0/N') unit = Rcomp() else: unit = inv_unit(a.unit) if a.value == 0: raise DPSemanticError('Division by zero') # TODO: what about integers? value = 1.0 / a.value return ValueWithUnits(value=value, unit=unit)
def plus_constants2_rcompunits(a, b): """ raises ConstantsNotCompatibleForAddition """ check_isinstance(a.unit, RcompUnits) check_isinstance(b.unit, RcompUnits) R = a.unit Fs = [a.unit, b.unit] values = [a.value, b.value] try: res = sum_units(Fs, values, R) except IncompatibleUnits: msg = 'The units "%s" and "%s" are incompatible.' % (a.unit.string, b.unit.string) raise DPSemanticError(msg) return ValueWithUnits(value=res, unit=R)
def run_ndp(ndp, functions): rnames = ndp.get_rnames() f = [] for fn in ndp.get_fnames(): vu = functions[fn] f.append(vu.value) f = tuple(f) if len(ndp.get_fnames()) == 1: f = f[0] dp = ndp.get_dp() if isinstance(dp, Constant): res = ValueWithUnits(dp.c, dp.R) elif isinstance(dp, WrapAMap): amap = dp.amap if len(rnames) == 1: res = ValueWithUnits(amap(f), dp.get_res_space()) else: res_R = ndp.get_rtypes(rnames) r = amap(f) assert isinstance(res_R, PosetProduct) and len(res_R) == len(rnames) assert isinstance(r, tuple) and len(r) == len(rnames) res = [ ValueWithUnits(value=value, unit=unit) for value, unit in zip(r, res_R.subs) ] else: raise NotImplementedError(type(dp)) if len(rnames) == 1: resources = {rnames[0]: res} else: resources = {} for i, rn in enumerate(rnames): resources[rn] = res[i] return resources
def eval_constant_collection(op, context): ops = get_odd_ops(unwrap_list(op.elements)) if len(ops) == 0: raise DPSemanticError('empty list') elements = [eval_constant(_, context) for _ in ops] e0 = elements[0] u0 = e0.unit elements = [_.cast_value(u0) for _ in elements] value = FiniteCollection(set(elements), u0) unit = FiniteCollectionsInclusion(u0) vu = ValueWithUnits(value, unit) return vu
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 apply(self, symbols, resources_or_constants, are_they_constant, context): # @UnusedVariable assert len(resources_or_constants) == 1 is_constant = are_they_constant[0] if is_constant: R = resources_or_constants[0].unit else: R = context.get_rtype(resources_or_constants[0]) dp = self.generate_dp(R) if is_constant: amap = dp.amap value = resources_or_constants[0].cast_value(amap.get_domain()) result = amap(value) vu = ValueWithUnits(result, amap.get_codomain()) return get_valuewithunits_as_resource(vu, context) else: r = resources_or_constants[0] return create_operation(context, dp, [r], name_prefix='_sqrt')
def plus_constants2(a, b): """ raises ConstantsNotCompatibleForAddition """ A = a.unit B = b.unit if isinstance(A, RcompUnits) and isinstance(B, RcompUnits): return plus_constants2_rcompunits(a, b) if isinstance(A, RcompUnits) and isinstance(B, (Rcomp, Nat)): try: b2A = b.cast_value(A) except NotLeq: msg = 'Cannot sum %s and %s.' % (A, B) raise_desc(ConstantsNotCompatibleForAddition, msg) b2 = ValueWithUnits(b2A, A) return plus_constants2_rcompunits(a, b2) if isinstance(B, RcompUnits) and isinstance(A, (Rcomp, Nat)): try: a2B = a.cast_value(B) except NotLeq: msg = 'Cannot sum %s and %s.' % (A, B) raise_desc(ConstantsNotCompatibleForAddition, msg) a2 = ValueWithUnits(a2B, B) return plus_constants2_rcompunits(a2, b) if isinstance(B, Rcomp) and isinstance(A, Rcomp): res = rcomp_add(a.value, b.value) return ValueWithUnits(value=res, unit=Rcomp()) if isinstance(B, Rcomp) and isinstance(A, Nat): a2v = a.cast_value(B) res = rcomp_add(a2v, b.value) return ValueWithUnits(value=res, unit=Rcomp()) if isinstance(A, Rcomp) and isinstance(B, Nat): b2v = b.cast_value(A) res = rcomp_add(a.value, b2v) return ValueWithUnits(value=res, unit=Rcomp()) if isinstance(B, Nat) and isinstance(A, Nat): res = Nat_add(a.value, b.value) return ValueWithUnits(value=res, unit=Nat()) msg = 'Cannot add %r and %r' % (a, b) raise DPNotImplementedError(msg)
def eval_constant_space_custom_value(op, context): from .eval_space_imp import eval_space assert isinstance(op, CDP.SpaceCustomValue) space = eval_space(op.space, context) custom_string = op.custom_string # print('custom string %r' % (custom_string).__repr__()) if isinstance(space, FiniteCollectionAsSpace): if custom_string == '*': if len(space.elements) == 1: value = list(space.elements)[0] return ValueWithUnits(unit=space, value=value) else: msg = 'You can use "*" only if the space has one element.' raise_desc(DPSemanticError, msg, elements=space.elements) try: space.belongs(custom_string) mcdp_dev_warning('this does not seem to work...') except NotBelongs: msg = 'The value "%s" is not an element of this poset.' % custom_string msg += '\n\nThese are the valid values: ' + ", ".join( map(str, space.elements)) + '.' raise_desc(DPSemanticError, msg) return ValueWithUnits(unit=space, value=op.custom_string) if isinstance(space, Nat): if isinstance(custom_string, CDP.ValueExpr): value = int(custom_string.value) # XXX: warn if value != custom_string.value: msg = 'Invalid value %s' % value raise_desc(DPSemanticError, msg, value=value, value0=custom_string.value) elif isinstance(custom_string, str): value = int(custom_string) else: msg = 'Cannot interpret value.' raise_desc(DPInternalError, msg, value=value) return ValueWithUnits(unit=Nat(), value=value) if isinstance(space, Int): mcdp_dev_warning('Top?') if isinstance(custom_string, CDP.ValueExpr): value = int(custom_string.value) # XXX: warn if value != custom_string.value: msg = 'Invalid value %s' % value raise_desc(DPSemanticError, msg, value=value, value0=custom_string.value) elif isinstance(custom_string, str): value = int(custom_string) else: msg = 'Cannot interpret value.' raise_desc(DPInternalError, msg, value=value) return ValueWithUnits(unit=Int(), value=value) if isinstance(space, Rcomp): mcdp_dev_warning('Top?') if isinstance(custom_string, CDP.ValueExpr): value = float(custom_string.value) elif isinstance(custom_string, str): value = float(custom_string) else: msg = 'Cannot interpret value.' raise_desc(DPInternalError, msg, value=value) return ValueWithUnits(unit=Rcomp(), value=value) msg = 'Custom parsing not implemented for space.' raise_desc(DPInternalError, msg, space=space, custom_string=custom_string)
def express_vu_in_isomorphic_space(vb, va): """ Returns vb in va's units """ from mcdp_posets.types_universe import express_value_in_isomorphic_space value = express_value_in_isomorphic_space(vb.unit, vb.value, va.unit) return ValueWithUnits(value=value, unit=va.unit)
def eval_constant_Bottom(op, context): from .eval_space_imp import eval_space # @Reimport space = eval_space(op.space, context) v = space.get_bottom() return ValueWithUnits(unit=space, value=v)
def passed_value(): return ValueWithUnits((), PosetProduct(()))
def eval_constant_IntConstant(op, context): # @UnusedVariable return ValueWithUnits(unit=Int(), value=op.value)
def eval_constant_Top(op, context): from .eval_space_imp import eval_space space = eval_space(op.space, context) v = space.get_top() return ValueWithUnits(unit=space, value=v)