def eval_lfunction_FValueBetween(r, context): from mcdp_dp import UncertainGateSym from .eval_lfunction_imp import eval_lfunction from .helpers import create_operation_lf fl = eval_lfunction(r.lower, context) fu = eval_lfunction(r.upper, context) F = context.get_ftype(fl) dp = UncertainGateSym(F) return create_operation_lf(context, dp=dp, functions=[fl, fu])
def eval_statement_SetNameFvalue(r, context): check_isinstance(r, CDP.SetNameFValue) name = r.name.value right_side = r.right_side if name in context.constants: msg = 'Constant %r already set.' % name raise DPSemanticError(msg, where=r.where) if name in context.var2resource: msg = 'Resource %r already set.' % name raise DPSemanticError(msg, where=r.where) if name in context.var2function: msg = 'Name %r already used.' % name raise DPSemanticError(msg, where=r.where) from .eval_lfunction_imp import eval_lfunction fv = eval_lfunction(right_side, context) ndp = context.names[fv.dp] # TODO: check that is not used anywhere current = fv.s updated = name try: ndp2 = ndp_rename_function(ndp, current=current, updated=updated) context.names[fv.dp] = ndp2 fv = CFunction(fv.dp, updated) except CouldNotRename: pass context.set_var2function(name, fv)
def eval_lfunction_FValuePlusOrMinus(r, context): from mcdp_dp import UncertainGateSym, MinusValueDP, PlusValueDP from .eval_lfunction_imp import eval_lfunction from .eval_constant_imp import eval_constant from .helpers import create_operation_lf check_isinstance(r, CDP.FValuePlusOrMinus) median = eval_lfunction(r.median, context) extent = eval_constant(r.extent, context) F = context.get_ftype(median) # provides f = between 10 g and 20 g # MinusValueDP : r + c ≥ f # PlusValueDP : r ≥ f + c # f <= f0 - c # pessimistic # f <= f0 + c # optimistic dpl = MinusValueDP(F, extent.value, extent.unit) dpu = PlusValueDP(F, extent.value, extent.unit) fl = create_operation_lf(context, dpl, functions=[median]) fu = create_operation_lf(context, dpu, functions=[median]) dp = UncertainGateSym(F) return create_operation_lf(context, dp=dp, functions=[fl, fu])
def eval_lfunction_Uncertain(r, context): from mcdp_dp import UncertainGateSym from .eval_lfunction_imp import eval_lfunction from .helpers import create_operation_lf assert isinstance(r, CDP.UncertainFun) fl = eval_lfunction(r.lower, context) fu = eval_lfunction(r.upper, context) F = context.get_ftype(fl) # Fu = context.get_rtype(fu) mcdp_dev_warning('Do explicit check of types.') dp = UncertainGateSym(F) return create_operation_lf(context, dp=dp, functions=[fl, fu])
def eval_statement_FunShortcut2(r, context): # provides rname <= (lf) from mcdp_lang.eval_lfunction_imp import eval_lfunction if isinstance(r.prep, CDP.leq): msg = 'This is deprecated, and should be "=".' warn_language(r.prep, MCDPWarnings.LANGUAGE_CONSTRUCT_DEPRECATED, msg, context) B = eval_lfunction(r.lf, context) check_isinstance(B, CFunction) F = context.get_ftype(B) A = add_function(r.fname.value, F, context, r) add_constraint(context, resource=A, function=B)
def eval_statement_FunShortcut2(r, context): # provides rname <= (lf) from mcdp_lang.eval_lfunction_imp import eval_lfunction if isinstance(r.prep, CDP.leq): msg = 'This is deprecated, and should be "=".' warn_language( r.prep, MCDPWarnings.LANGUAGE_CONSTRUCT_DEPRECATED, msg, context) B = eval_lfunction(r.lf, context) check_isinstance(B, CFunction) F = context.get_ftype(B) A = add_function(r.fname.value, F, context, r) add_constraint(context, resource=A, function=B)
def eval_lfunction_tupleindexfun(f, context): from mcdp_lang.eval_lfunction_imp import eval_lfunction fvalue = eval_lfunction(f.value, context) index = f.index F = context.get_ftype(fvalue) n = len(F.subs) if not (0 <= index < n): msg = 'Out of bounds.' raise_desc(DPSemanticError, msg, index=index, F=F) return context.ifun_get_index(fvalue, index)
def eval_MakeTuple_as_lfunction(mt, context): from mcdp_lang.eval_lfunction_imp import eval_lfunction ops = get_odd_ops(unwrap_list(mt.ops)) functions = [eval_lfunction(_, context) for _ in ops] Rs = [context.get_ftype(_) for _ in functions] R = PosetProduct(tuple(Rs)) # Now it's easy - this corresponds to a simple Mux operation coords = list(range(len(Rs))) dp = TakeRes(R, coords) return create_operation_lf(context, dp=dp, functions=functions, name_prefix='_demake_tuple', op_prefix='_factors', res_prefix='_result')
def eval_lfunction_label_index(r, context): from mcdp_lang.eval_lfunction_imp import eval_lfunction assert isinstance(r, CDP.FunctionLabelIndex) assert isinstance(r.label, CDP.IndexLabel), r.label label = r.label.label fvalue = eval_lfunction(r.fvalue, context) R = context.get_ftype(fvalue) if not isinstance(R, PosetProductWithLabels): msg = 'Cannot index by label for this space.' raise_desc(DPSemanticError, msg, space=R, label=label) if not label in R.labels: msg = 'Cannot find label %r in %r.' % (label, R.labels) raise_desc(DPSemanticError, msg, space=R) index = R.labels.index(label) return context.ifun_get_index(fvalue, index)
def eval_lfunction_FValuePlusOrMinusPercent(r, context): from mcdp_lang.eval_lfunction_imp import eval_lfunction from mcdp_lang.helpers import create_operation_lf from mcdp_dp import InvMultValueDP, UncertainGateSym check_isinstance(r, CDP.FValuePlusOrMinusPercent) median = eval_lfunction(r.median, context) check_isinstance(r.perc, CDP.ValueExpr) p0 = r.perc.value pl = 1 - p0 / 100.0 pu = 1 + p0 / 100.0 Rl = context.get_ftype(median) dpl = InvMultValueDP(Rl, Rl, R_dimensionless, pl) dpu = InvMultValueDP(Rl, Rl, R_dimensionless, pu) rl = create_operation_lf(context, dpl, functions=[median]) ru = create_operation_lf(context, dpu, functions=[median]) dp = UncertainGateSym(Rl) return create_operation_lf(context, dp=dp, functions=[rl, ru])
def parse_as_fvalue(s): """ returns fvalue, context """ parsed = parse_wrap(Syntax.fvalue, s)[0] context = Context() r = eval_lfunction(parsed, context) return r, context
def eval_statement(r, context): check_isinstance(context, ModelBuildingContext) from .eval_resources_imp import eval_rvalue from .eval_lfunction_imp import eval_lfunction invalid = (CDP.ConstraintInvalidRR, CDP.ConstraintInvalidFF, CDP.ConstraintInvalidSwapped) if isinstance(r, invalid): msg = 'This constraint is invalid. ' if isinstance(r, CDP.ConstraintInvalidRR): msg += 'Both sides are resources.' if isinstance(r, CDP.ConstraintInvalidFF): msg += 'Both sides are functionalities.' if isinstance(r, CDP.ConstraintInvalidSwapped): msg += ('Functionality and resources are on the wrong side ' 'of the inequality.') raise DPSemanticError(msg) if isinstance(r, Connection): context.add_connection(r) elif isinstance(r, CDP.Constraint): resource = eval_rvalue(r.rvalue, context) function = eval_lfunction(r.fvalue, context) try: add_constraint(context, resource, function) except MCDPExceptionWithWhere as e: _, _, tb = sys.exc_info() where = r.prep.where # indicate preposition "<=" raise_with_info(e, where, tb) elif isinstance(r, CDP.VarStatement): P = eval_space(r.unit, context) vnames = get_odd_ops(unwrap_list(r.vnames)) for v in vnames: vname = v.value where = v.where add_variable(vname, P, where, context) elif isinstance(r, CDP.SetNameNDPInstance): name = r.name.value ndp = eval_ndp(r.dp_rvalue, context) context.add_ndp(name, ndp) elif isinstance(r, CDP.SetNameMCDPType): name = r.name.value right_side = r.right_side x = eval_ndp(right_side, context) context.set_var2model(name, x) elif isinstance(r, CDP.SetNameRValue): return eval_statement_SetNameRValue(r, context) elif isinstance(r, CDP.SetNameConstant): return eval_statement_SetNameConstant(r, context) elif isinstance(r, CDP.SetNameFValue): return eval_statement_SetNameFvalue(r,context) elif isinstance(r, CDP.IgnoreFun): # equivalent to f >= any-of(Minimals S) lf = eval_lfunction(r.fvalue, context) F = context.get_ftype(lf) values = F.get_minimal_elements() dp = ConstantMinimals(F, values) ndp = SimpleWrap(dp, fnames=[], rnames='_out') name = context.new_name('_constant') context.add_ndp(name, ndp) r = context.make_resource(name, '_out') add_constraint(context, resource=r, function=lf) elif isinstance(r, CDP.IgnoreRes): # equivalent to r <= any-of(Maximals S) rv = eval_rvalue(r.rvalue, context) R = context.get_rtype(rv) try: values = R.get_maximal_elements() except NotImplementedError as e: # pragma: no cover msg = 'Could not call get_maximal_elements().' raise_wrapped(DPInternalError, e, msg, R=R) dp = LimitMaximals(R, values) ndp = SimpleWrap(dp, fnames='_limit', rnames=[]) name = context.new_name('_limit') context.add_ndp(name, ndp) f = context.make_function(name, '_limit') add_constraint(context, resource=rv, function=f) else: cases = { CDP.ResStatement: eval_statement_ResStatement, CDP.FunStatement: eval_statement_FunStatement, CDP.FunShortcut5: eval_statement_FunShortcut5, CDP.ResShortcut5: eval_statement_ResShortcut5, CDP.ResShortcut4: eval_statement_ResShortcut4, CDP.FunShortcut4: eval_statement_FunShortcut4, CDP.FunShortcut1m: eval_statement_FunShortcut1m, CDP.ResShortcut1m: eval_statement_ResShortcut1m, CDP.FunShortcut2: eval_statement_FunShortcut2, CDP.ResShortcut2: eval_statement_ResShortcut2, CDP.FunShortcut1: eval_statement_FunShortcut1, CDP.ResShortcut1: eval_statement_ResShortcut1, } for klass, hook in cases.items(): if isinstance(r, klass): return hook(r, context) if True: # pragma: no cover msg = 'eval_statement(): cannot interpret.' r2 = recursive_print(r) raise_desc(DPInternalError, msg, r=r2) # where=r.where.__repr__())
def eval_statement_SetNameRValue(r, context): """ This is a special case, because it is the place where the syntax is ambiguous. x = Nat: 1 + r could be interpreted with r being a functionality or a resource. By default it is parsed as SetNameRValue, and so we get here. We check whether it could be parsed as setname_fvalue, and warn about that. """ from .eval_resources_imp import eval_rvalue from .eval_constant_imp import NotConstant from .eval_lfunction_imp import eval_lfunction from .syntax import Syntax check_isinstance(r, CDP.SetNameRValue) # Check to see if this could have been interpreted using # setname_fvalue # Try to have an alternative parsing of the string as # Syntax.setname_fvalue try: w = r.where s = w.string[w.character:w.character_end] alt = parse_wrap(Syntax.setname_fvalue, s)[0] # print('alternative: %s' % recursive_print(alt)) except Exception as _: # XXX: which one? #print "No, it does not parse: %s" % traceback.format_exc(e) alt = None name = r.name.value right_side = r.right_side if name in context.constants: msg = 'Constant %r already set.' % name raise DPSemanticError(msg, where=r.where) if name in context.var2resource: msg = 'Resource %r already set.' % name raise DPSemanticError(msg, where=r.where) if name in context.var2function: msg = 'Name %r already used.' % name raise DPSemanticError(msg, where=r.where) try: x = eval_constant(right_side, context) context.set_constant(name, x) used_constant = True except NotConstant: used_constant = False try: x = eval_rvalue(right_side, context) ndp1 = context.names[x.dp] current = x.s updated = name try: ndp2 = ndp_rename_resource(ndp1, current=current, updated=updated) context.names[x.dp] = ndp2 x = CResource(x.dp, updated) except CouldNotRename: pass context.set_var2resource(name, x) used_rvalue = True except DPSemanticError as e: if 'not declared' in str(e) and alt is not None: # XXX: this seems not to be used anymore # after we implemented the interpretation at the syntax level raise NotImplementedError x = eval_lfunction(alt.right_side, context) context.set_var2function(name, x) used_rvalue = False else: raise if alt is not None: msg = ('This expression could be parsed both as a functionality ' 'and as a resource.') if used_constant: pass # msg += ' I parsed it as a constant.' else: if used_rvalue: msg += ' I parsed it as a resource.' else: msg += ' I parsed it as a function.' warn_language(r, MCDPWarnings.LANGUAGE_AMBIGUOS_EXPRESSION, msg, context)
def eval_statement(r, context): check_isinstance(context, ModelBuildingContext) from .eval_resources_imp import eval_rvalue from .eval_lfunction_imp import eval_lfunction invalid = (CDP.ConstraintInvalidRR, CDP.ConstraintInvalidFF, CDP.ConstraintInvalidSwapped) if isinstance(r, invalid): msg = 'This constraint is invalid. ' if isinstance(r, CDP.ConstraintInvalidRR): msg += 'Both sides are resources.' if isinstance(r, CDP.ConstraintInvalidFF): msg += 'Both sides are functionalities.' if isinstance(r, CDP.ConstraintInvalidSwapped): msg += ('Functionality and resources are on the wrong side ' 'of the inequality.') raise DPSemanticError(msg) if isinstance(r, Connection): context.add_connection(r) elif isinstance(r, CDP.Constraint): resource = eval_rvalue(r.rvalue, context) function = eval_lfunction(r.fvalue, context) try: add_constraint(context, resource, function) except MCDPExceptionWithWhere as e: _, _, tb = sys.exc_info() where = r.prep.where # indicate preposition "<=" raise_with_info(e, where, tb) elif isinstance(r, CDP.VarStatement): P = eval_space(r.unit, context) vnames = get_odd_ops(unwrap_list(r.vnames)) for v in vnames: vname = v.value where = v.where add_variable(vname, P, where, context) elif isinstance(r, CDP.SetNameNDPInstance): name = r.name.value ndp = eval_ndp(r.dp_rvalue, context) if name in context.names: msg = 'Repeated identifier "%s".' % name raise DPSemanticError(msg, where=r.name.where) context.add_ndp(name, ndp) elif isinstance(r, CDP.SetNameMCDPType): name = r.name.value right_side = r.right_side x = eval_ndp(right_side, context) context.set_var2model(name, x) elif isinstance(r, CDP.SetNameRValue): return eval_statement_SetNameRValue(r, context) elif isinstance(r, CDP.SetNameConstant): return eval_statement_SetNameConstant(r, context) elif isinstance(r, CDP.SetNameFValue): return eval_statement_SetNameFvalue(r, context) elif isinstance(r, CDP.Implements): return eval_statement_implements(r, context) elif isinstance(r, CDP.IgnoreFun): # equivalent to f >= any-of(Minimals S) lf = eval_lfunction(r.fvalue, context) F = context.get_ftype(lf) values = F.get_minimal_elements() dp = ConstantMinimals(F, values) ndp = SimpleWrap(dp, fnames=[], rnames='_out') name = context.new_name('_constant') context.add_ndp(name, ndp) r = context.make_resource(name, '_out') add_constraint(context, resource=r, function=lf) elif isinstance(r, CDP.IgnoreRes): # equivalent to r <= any-of(Maximals S) rv = eval_rvalue(r.rvalue, context) R = context.get_rtype(rv) try: values = R.get_maximal_elements() except NotImplementedError as e: # pragma: no cover msg = 'Could not call get_maximal_elements().' raise_wrapped(DPInternalError, e, msg, R=R) dp = LimitMaximals(R, values) ndp = SimpleWrap(dp, fnames='_limit', rnames=[]) name = context.new_name('_limit') context.add_ndp(name, ndp) f = context.make_function(name, '_limit') add_constraint(context, resource=rv, function=f) else: cases = { CDP.ResStatement: eval_statement_ResStatement, CDP.FunStatement: eval_statement_FunStatement, CDP.FunShortcut5: eval_statement_FunShortcut5, CDP.ResShortcut5: eval_statement_ResShortcut5, CDP.ResShortcut4: eval_statement_ResShortcut4, CDP.FunShortcut4: eval_statement_FunShortcut4, CDP.FunShortcut1m: eval_statement_FunShortcut1m, CDP.ResShortcut1m: eval_statement_ResShortcut1m, CDP.FunShortcut2: eval_statement_FunShortcut2, CDP.ResShortcut2: eval_statement_ResShortcut2, CDP.FunShortcut1: eval_statement_FunShortcut1, CDP.ResShortcut1: eval_statement_ResShortcut1, CDP.SetNameUncertainConstant: eval_statement_SetNameUncertainConstant, } for klass, hook in cases.items(): if isinstance(r, klass): return hook(r, context) if True: # pragma: no cover msg = 'eval_statement(): cannot interpret.' r2 = recursive_print(r) raise_desc(DPInternalError, msg, r=r2) # where=r.where.__repr__())