def fix_functions_with_multiple_connections(context): # tuples (ndp, res) from mocdp.comp.connection import find_functions_with_multiple_connections res = find_functions_with_multiple_connections(context.connections) for id_ndp, fname in res: matches = lambda c: c.dp2 == id_ndp and c.s2 == fname its = [c for c in context.connections if matches(c)] assert len(its) >= 2 for c in its: context.connections.remove(c) P = context.get_ftype(CFunction(id_ndp, fname)) new_name = context.new_name('_join_fname') dp = JoinNDP(n=len(its), P=P) new_connections = [] fnames = [] rname = '_a' for i, c in enumerate(its): fn = '_%s_%d' % (fname, i) fnames.append(fn) c2 = Connection(dp1=c.dp1, s1=c.s1, dp2=new_name, s2=fn) new_connections.append(c2) ndp = dpwrap(dp, fnames, rname) context.add_ndp(new_name, ndp) for c2 in new_connections: context.add_connection(c2) cc = Connection(dp1=new_name, s1=rname, dp2=id_ndp, s2=fname) context.add_connection(cc)
def get_valuewithunits_as_function(v, context): dp = Limit(v.unit, v.value) n = context.new_name('_lim') sn = context.new_fun_name('_l') ndp = dpwrap(dp, sn, []) context.add_ndp(n, ndp) return context.make_function(n, sn)
def add_variable(vname, P, where, context): if vname in context.variables: msg = 'Variable name %r already used once.' % vname raise DPSemanticError(msg, where=where) if vname in context.rnames: msg = 'Conflict between variable and resource name %r.' % vname raise DPSemanticError(msg, where=where) if vname in context.fnames: msg = 'Conflict between variable and functionality name %r.' % vname raise DPSemanticError(msg, where=where) if vname in context.var2resource: msg = 'The name %r is already used as a resource.' % vname raise DPSemanticError(msg, where=where) if vname in context.var2function: msg = 'The name %r is already used as a functionality.' % vname raise DPSemanticError(msg, where=where) dp = VariableNode(P, vname) fname = '_' + vname rname = '_' + vname ndp = dpwrap(dp, fname, rname) context.add_ndp(vname, ndp) context.set_var2resource(vname, CResource(vname, rname)) context.set_var2function(vname, CFunction(vname, fname)) context.variables.add(vname)
def fix_resources_with_multiple_connections(context): # tuples (ndp, res) from mocdp.comp.connection import find_resources_with_multiple_connections res = find_resources_with_multiple_connections(context.connections) for id_ndp, rname in res: matches = lambda c: c.dp1 == id_ndp and c.s1 == rname its = [c for c in context.connections if matches(c)] assert len(its) >= 2 for c in its: context.connections.remove(c) P = context.get_rtype(CResource(id_ndp, rname)) new_name = context.new_name('_join_fname') dp = MeetNDualDP(n=len(its), P=P) new_connections = [] rnames = [] for i, c in enumerate(its): rn = '_%s_%d' % (rname, i) rnames.append(rn) c2 = Connection(dp1=new_name, s1=rn, dp2=c.dp2, s2=c.s2) new_connections.append(c2) fname = '_a' ndp = dpwrap(dp, fname, rnames) context.add_ndp(new_name, ndp) for c2 in new_connections: context.add_connection(c2) # [ id_ndp : rname ] -> [ new_name ] cc = Connection(dp2=new_name, s2=fname, dp1=id_ndp, s1=rname) context.add_connection(cc)
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 get_constant_minimals_as_resources(R, values, context): for v in values: R.belongs(v) dp = ConstantMinimals(R=R, values=values) nres = context.new_res_name('_c') ndp = dpwrap(dp, [], nres) context.add_ndp(nres, ndp) return context.make_resource(nres, nres)
def get_constant_maximals_as_function(F, values, context): for v in values: F.belongs(v) dp = LimitMaximals(F=F, values=values) nres = context.new_name('_c') ndp = dpwrap(dp, '_max', []) context.add_ndp(nres, ndp) return context.make_function(nres, '_max')
def add_variable(vname, P, where, context): if vname in context.variables: msg = 'Variable name %r already used once.' % vname raise DPSemanticError(msg, where=where) if vname in context.rnames: msg = 'Conflict between variable and resource name %r.' % vname raise DPSemanticError(msg, where=where) if vname in context.fnames: msg = 'Conflict between variable and functionality name %r.' % vname raise DPSemanticError(msg, where=where) if vname in context.var2resource: msg = 'The name %r is already used as a resource.' % vname raise DPSemanticError(msg, where=where) if vname in context.var2function: msg = 'The name %r is already used as a functionality.' % vname raise DPSemanticError(msg, where=where) try: check_good_name_for_regular_node(vname) except ValueError as e: msg = 'Invalid name: %s' % e raise DPSemanticError(msg, where=where) dp = VariableNode(P, vname) fname = '_' + vname rname = '_' + vname ndp = dpwrap(dp, fname, rname) context.add_ndp(vname, ndp) context.set_var2resource(vname, CResource(vname, rname)) context.set_var2function(vname, CFunction(vname, fname)) context.variables.add(vname)
def eval_ndp_catalogue3(r, context): check_isinstance(r, CDP.Catalogue3) 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() rows = unwrap_list(r.table) entries = [] # (name, f, r) for i, row in enumerate(rows): check_isinstance(row, CDP.CatalogueRow3) check_isinstance(row.functions, CDP.CatalogueFunc) row.leftright check_isinstance(row.resources, CDP.CatalogueRes) fs = get_odd_ops(unwrap_list(row.functions.ops)) rs = get_odd_ops(unwrap_list(row.resources.ops)) for _ in list(fs) + list(rs): if isinstance(_, CDP.CatalogueEntryConstantUncertain): msg = 'Uncertain catalogue not implemented' raise DPNotImplementedError(msg, where=_.where) fs_evaluated = [eval_constant(_.constant, context) for _ in fs] rs_evaluated = [eval_constant(_.constant, context) for _ in rs] if len(Fs) == 0: # expect <> if len(fs) != 1 and fs_evaluated.value != (): msg = 'Because there are no functionalities, I expected simply "<>".' raise DPSemanticError(msg, where=row.functions.where) else: if len(fs_evaluated) != len(Fs): msg = 'Mismatch with number of functionalities.' raise DPSemanticError(msg, where=row.functions.where) if len(Rs) == 0: if len(rs) != 1 and rs_evaluated.value != (): msg = 'Because there are no resources, I expected simply "<>".' raise DPSemanticError(msg, where=row.resources.where) else: if len(rs_evaluated) != len(Rs): msg = 'Mismatch with number of resources.' raise DPSemanticError(msg, where=row.resources.where) for cell, Fhave, F in zip(fs, fs_evaluated, Fs): try: tu.check_leq(Fhave.unit, F) except NotLeq: msg = 'Dimensionality problem: cannot convert %s to %s.' % ( Fhave.unit, F) raise DPSemanticError(msg, where=cell.where) for cell, Rhave, R in zip(rs, rs_evaluated, Rs): try: tu.check_leq(Rhave.unit, R) except NotLeq: msg = 'Dimensionality problem: cannot convert %s to %s.' % ( Rhave.unit, R) raise DPSemanticError(msg, where=cell.where) fvalues_ = [_.cast_value(F) for (_, F) in zip(fs_evaluated, Fs)] rvalues_ = [_.cast_value(R) for (_, R) in zip(rs_evaluated, Rs)] assert len(fvalues_) == len(fun) assert len(rvalues_) == len(res) f = tuple(fvalues_) r = tuple(rvalues_) if len(Fs) == 0: f = () if len(Rs) == 0: r = () entries.append((i, f, r)) 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_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 create_operation(context, dp, resources, name_prefix=None, op_prefix=None, res_prefix=None): """ This is useful to create operations that take possibly many inputs and produce one output. Example use: R = mult_table_seq(resources_types) dp = ProductN(tuple(resources_types), R) from mcdp_lang.helpers import create_operation r = create_operation(context, dp, resources, name_prefix='_prod', op_prefix='_factor', res_prefix='_result') """ if name_prefix is None: name_prefix = '_%s' % type(dp).__name__ # new name for the ndp name = context.new_name(name_prefix) if op_prefix is None: op_prefix = '_op' if res_prefix is None: res_prefix = '_res' name_result = context.new_res_name(res_prefix) connections = [] fnames = [] for i, r in enumerate(resources): ni = context.new_fun_name('%s%s' % (op_prefix, i)) fnames.append(ni) fnames_ = fnames[0] if len(fnames) == 1 else fnames ndp = dpwrap(dp, fnames_, name_result) context.add_ndp(name, ndp) tu = get_types_universe() for i, r in enumerate(resources): # this is where we check for types # source resource R = context.get_rtype(r) # function F = ndp.get_ftype(fnames[i]) if not tu.equal(F, R): conversion = get_conversion(R, F) if conversion is None: msg = 'I need a conversion from %s to %s' % (R, F) raise DPInternalError(msg) else: r = create_operation(context, conversion, [r], name_prefix='_conversion_for_%s' % name_result) R = context.get_rtype(r) assert tu.equal(F, R) c = Connection(dp1=r.dp, s1=r.s, dp2=name, s2=fnames[i]) connections.append(c) for c in connections: context.add_connection(c) res = context.make_resource(name, name_result) return res
def get_valuewithunits_as_resource(v, context): dp = Constant(R=v.unit, value=v.value) nres = context.new_res_name('_c') ndp = dpwrap(dp, [], nres) context.add_ndp(nres, ndp) return context.make_resource(nres, nres)
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 create_operation_lf(context, dp, functions, name_prefix=None, op_prefix='_op', res_prefix='_res', allow_conversion=True): if name_prefix is None: name_prefix = '_%s' % type(dp).__name__ 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 create_operation(context, dp, resources, name_prefix, op_prefix=None, res_prefix=None): """ This is useful to create operations that take possibly many inputs and produce one output. Example use: R = mult_table_seq(resources_types) dp = ProductN(tuple(resources_types), R) from mcdp_lang.helpers import create_operation r = create_operation(context, dp, resources, name_prefix='_prod', op_prefix='_factor', res_prefix='_result') """ # new name for the ndp name = context.new_name(name_prefix) if op_prefix is None: op_prefix = '_op' if res_prefix is None: res_prefix = '_res' name_result = context.new_res_name(res_prefix) connections = [] fnames = [] for i, r in enumerate(resources): ni = context.new_fun_name('%s%s' % (op_prefix, i)) fnames.append(ni) fnames_ = fnames[0] if len(fnames) == 1 else fnames ndp = dpwrap(dp, fnames_, name_result) context.add_ndp(name, ndp) tu = get_types_universe() for i, r in enumerate(resources): # this is where we check for types # source resource R = context.get_rtype(r) # function F = ndp.get_ftype(fnames[i]) if not tu.equal(F, R): conversion = get_conversion(R, F) if conversion is None: msg = 'I need a conversion from %s to %s' % (R, F) raise DPInternalError(msg) else: r = create_operation(context, conversion, [r], name_prefix='_conversion_for_%s' % name_result) R = context.get_rtype(r) assert tu.equal(F, R) c = Connection(dp1=r.dp, s1=r.s, dp2=name, s2=fnames[i]) connections.append(c) for c in connections: context.add_connection(c) res = context.make_resource(name, name_result) return res