def transform(name2, ndp2): # Returns name, ndp isf, fname = is_fun_node_name(name2) isr, rname = is_res_node_name(name2) if isf or isr: if isinstance(ndp2, SimpleWrap): if isf: fnames = "%s%s%s" % (prefix, sep, fname) rnames = "%s%s%s" % (prefix, sep, fname) if isr: fnames = "%s%s%s" % (prefix, sep, rname) rnames = "%s%s%s" % (prefix, sep, rname) dp = ndp2.dp res = SimpleWrap(dp=dp, fnames=fnames, rnames=rnames) elif isinstance(ndp2, LabelerNDP): ndp_inside = transform(name2, ndp2.ndp) return LabelerNDP(ndp_inside, ndp2.recursive_name) else: raise NotImplementedError(type(ndp2)) else: res = flatten_add_prefix(ndp2, prefix) return res
def abstract(self): if not self.context.names: # this means that there are nor children, nor functions nor resources dp = Mux(PosetProduct(()), ()) ndp = SimpleWrap(dp, fnames=[], rnames=[]) return ndp try: self.check_fully_connected() except NotConnected as e: msg = 'Cannot abstract because not all subproblems are connected.' raise_wrapped(DPSemanticError, e, msg, exc=sys.exc_info(), compact=True) from mocdp.comp.composite_abstraction import cndp_abstract res = cndp_abstract(self) assert isinstance(res, SimpleWrap), type(res) assert res.get_fnames() == self.context.fnames assert res.get_rnames() == self.context.rnames return res
def simplewrap_relabel(sw, fun_map, res_map): fnames2 = [ fun_map.get(_, _) for _ in sw.get_fnames()] rnames2 = [ res_map.get(_, _) for _ in sw.get_rnames()] if len(fnames2) == 1: fnames2 = fnames2[0] if len(rnames2) == 1: rnames2 = rnames2[0] return SimpleWrap(sw.dp, fnames2, rnames2, icon=sw.icon)
def abstract(self): dp = self.get_dp() fnames = self.get_fnames() rnames = self.get_rnames() if len(fnames) == 1: fnames = fnames[0] if len(rnames) == 1: rnames = rnames[0] return SimpleWrap(dp, fnames=fnames, rnames=rnames)
def ndps_parallel(ndps): dps = [ndp.get_dp() for ndp in ndps] dp = make_parallel_n(dps) F = dp.get_fun_space() R = dp.get_res_space() fnames = [] ftypes = [] rnames = [] rtypes = [] coords_postfix = [] coords_prefix = [] for i, ndp_i in enumerate(ndps): fnames_i = ndp_i.get_fnames() if not fnames_i: coords_prefix.append([]) else: mine = [] for j, fn in enumerate(fnames_i): ft = ndp_i.get_ftype(fn) F0_index = len(fnames) mine.append(F0_index) fnames.append(fn) ftypes.append(ft) if len(mine) == 1: mine = mine[0] coords_prefix.append(mine) rnames_i = ndp_i.get_rnames() for j, rn in enumerate(rnames_i): rt = ndp_i.get_rtype(rn) if len(rnames_i) == 1: coords_postfix.append(i) else: coords_postfix.append((i, j)) rnames.append(rn) rtypes.append(rt) F0 = PosetProduct(ftypes) prefix = Mux(F0, coords_prefix) assert F == prefix.get_res_space() R0 = PosetProduct(rtypes) postfix = Mux(R, coords_postfix) assert R0 == postfix.get_res_space() res_dp = make_series(make_series(prefix, dp), postfix) from mocdp.comp.connection import simplify_if_only_one_name res_dp, fnames, rnames = simplify_if_only_one_name(res_dp, fnames, rnames) res = SimpleWrap(res_dp, fnames, rnames) return res
def ifun_get_index(self, cf, index): from mcdp_dp.dp_flatten import TakeFun from mocdp.comp.wrap import SimpleWrap if not cf in self.indexed_fun: F = self.get_ftype(cf) n = len(F.subs) # todo: use labels if isinstance(F, PosetProductWithLabels): fnames = list(F.labels) else: fnames = ['_f%d' % i for i in range(n)] coords = list(range(n)) dp = TakeFun(F, coords) ndp_out = '_muxed' ndp = SimpleWrap(dp, fnames=fnames, rnames=ndp_out) ndp_name = self.new_name('_indexing') self.add_ndp(ndp_name, ndp) c = Connection(dp1=ndp_name, s1=ndp_out, dp2=cf.dp, s2=cf.s) self.add_connection(c) self.indexed_fun[cf] = ndp_name ndp_name = self.indexed_fun[cf] ndp = self.names[ndp_name] fnames = ndp.get_fnames() n = len(fnames) s = fnames[index] if not (0 <= index < n): msg = 'Out of bounds.' raise_desc(DPSemanticError, msg, index=index, F=F) res = self.make_function(ndp_name, s) return res
def ires_get_index(self, cr, index): from mcdp_dp.dp_flatten import TakeRes from mocdp.comp.wrap import SimpleWrap if not cr in self.indexed_res: R = self.get_rtype(cr) n = len(R.subs) # todo: use labels if isinstance(R, PosetProductWithLabels): rnames = list(R.labels) else: rnames = ['_r%d' % i for i in range(n)] coords = list(range(n)) dp = TakeRes(R, coords) ndp_out = '_muxed' ndp = SimpleWrap(dp, fnames=ndp_out, rnames=rnames) ndp_name = self.new_name('_indexing') self.add_ndp(ndp_name, ndp) c = Connection(dp2=ndp_name, s2=ndp_out, dp1=cr.dp, s1=cr.s) self.add_connection(c) self.indexed_res[cr] = ndp_name ndp_name = self.indexed_res[cr] ndp = self.names[ndp_name] rnames = ndp.get_rnames() n = len(rnames) s = rnames[index] if not (0 <= index < n): msg = 'Out of bounds.' raise_desc(DPSemanticError, msg, index=index, R=R) res = self.make_resource(ndp_name, s) return res
def get_dummy(fnames, rnames): base = (Rcomp(),) F = PosetProduct(base * len(fnames)) R = PosetProduct(base * len(rnames)) if len(fnames) == 1: F = F[0] if len(rnames) == 1: R = R[0] if len(fnames) == 1: fnames = fnames[0] if len(rnames) == 1: rnames = rnames[0] return SimpleWrap(Dummy(F, R), fnames, rnames)
def eval_ndp_approx_lower(r, context): from mcdp_lang.eval_ndp_imp import eval_ndp from mcdp_dp.dp_transformations import get_dp_bounds nl = r.level ndp = eval_ndp(r.ndp, context) dp = ndp.get_dp() mcdp_dev_warning('make it better') dpl, _ = get_dp_bounds(dp, nl, 1) fnames = ndp.get_fnames() rnames = ndp.get_rnames() rnames = rnames if len(rnames) > 1 else rnames[0] fnames = fnames if len(fnames) > 1 else fnames[0] ndp2 = SimpleWrap(dpl, fnames, rnames) return ndp2
def add_muxes(inner, cs, s_muxed, inner_name='_inner0', mux1_name='_mux1', mux2_name='_mux2'): """ Add muxes before and after inner ---(extraf)--| |---(extrar)-- |--c1-----| inner |--c1--| s_muxed-|--c2-----| |--c2--|--s_muxed """ extraf = [f for f in inner.get_fnames() if not f in cs] extrar = [r for r in inner.get_rnames() if not r in cs] fnames = extraf + [s_muxed] rnames = extrar + [s_muxed] name2ndp = {} connections = [] name2ndp[inner_name] = inner # Second mux if len(cs) == 1: F = inner.get_ftype(cs[0]) nto1 = SimpleWrap(Identity(F), fnames=cs[0], rnames=s_muxed) else: types = inner.get_ftypes(cs) F = PosetProduct(types.subs) # [0, 1, 2] coords = list(range(len(cs))) mux = Mux(F, coords) nto1 = SimpleWrap(mux, fnames=cs, rnames=s_muxed) if len(cs) == 1: R = inner.get_rtype(cs[0]) _1ton = SimpleWrap(Identity(R), fnames=s_muxed, rnames=cs[0]) else: # First mux coords = list(range(len(cs))) R = mux.get_res_space() mux2 = Mux(R, coords) _1ton = SimpleWrap(mux2, fnames=s_muxed, rnames=cs) F2 = mux2.get_res_space() tu = get_types_universe() tu.check_equal(F, F2) name2ndp[mux1_name] = nto1 name2ndp[mux2_name] = _1ton for n in cs: connections.append(Connection(inner_name, n, mux1_name, n)) for n in cs: connections.append(Connection(mux2_name, n, inner_name, n)) # Now add the remaining names connect_functions_to_outside(name2ndp, connections, ndp_name=inner_name, fnames=extraf) connect_resources_to_outside(name2ndp, connections, ndp_name=inner_name, rnames=extrar) connect_resources_to_outside(name2ndp, connections, ndp_name=mux1_name, rnames=[s_muxed]) connect_functions_to_outside(name2ndp, connections, ndp_name=mux2_name, fnames=[s_muxed]) outer = CompositeNamedDP.from_parts(name2ndp=name2ndp, connections=connections, fnames=fnames, rnames=rnames) return outer
def cndp_abstract_loop2(ndp): """ Abstracts the dp using the canonical form """ from .composite_makecanonical import get_canonical_elements res = get_canonical_elements(ndp) cycles = res['cycles'] if len(cycles) > 1: msg = ( 'I expected that the cycles were already compacted, while %s remain.' % cycles) raise_desc(NotImplementedError, msg, res=res) inner = res['inner'] inner_dp = inner.get_dp() extraf = res['extraf'] extrar = res['extrar'] # print 'ndp', ndp.get_fnames(), ndp.get_rnames() # print 'inner', inner.get_fnames(), inner.get_rnames() # print 'extra', extraf, extrar # print 'cycles', res['cycles'] assert extraf == ndp.get_fnames(), (extraf, ndp.get_fnames()) assert extrar == ndp.get_rnames(), (extrar, ndp.get_rnames()) # We use the ndp layer to create a dp that has F1 = ndp.get_ftypes(extraf) R1 = ndp.get_rtypes(extrar) # if len(cycles) > 1: # msg = 'Expected there would be at most one cycle, found: %d.' % len(cycles) # raise_desc(Exception, msg, ndp=ndp) if len(cycles) == 0: # raise NotImplementedError() mcdp_dev_warning('this needs much more testing') dp = inner_dp fnames = extraf rnames = extrar if len(fnames) == 1: fnames = fnames[0] if len(rnames) == 1: rnames = rnames[0] from mocdp.comp.wrap import dpwrap return dpwrap(dp, fnames, rnames) F2 = inner.get_rtype(cycles[0]) R2 = F2 dp0F = PosetProduct((F1, F2)) coords1 = [] for inner_fname in inner.get_fnames(): if inner_fname in extraf: coords1.append((0, extraf.index(inner_fname))) else: coords1.append(1) if len(coords1) == 1: coords1 = coords1[0] mux1 = Mux(dp0F, coords1) assert mux1.get_res_space() == inner_dp.get_fun_space() mux0F = inner_dp.get_res_space() coords2extra = [] for rname in extrar: i = inner.get_rnames().index(rname) if len(inner.get_rnames()) == 1: i = () coords2extra.append(i) j = inner.get_rnames().index(cycles[0]) if len(inner.get_rnames()) == 1: j = () coords2 = [coords2extra, j] mux2 = Mux(mux0F, coords2) dp0 = make_series(make_series(mux1, inner_dp), mux2) dp0R_expect = PosetProduct((R1, R2)) assert dp0.get_res_space() == dp0R_expect dp = DPLoop2(dp0) # this is what we want to obtain at the end F = ndp.get_ftypes(ndp.get_fnames()) if len(ndp.get_fnames()) == 1: F = F[0] R = ndp.get_rtypes(ndp.get_rnames()) if len(ndp.get_rnames()) == 1: R = R[0] if len(extraf) == 1: dp = make_series(Mux(F, [()]), dp) if len(extrar) == 1: dp = make_series(dp, Mux(PosetProduct((R, )), 0)) tu = get_types_universe() tu.check_equal(dp.get_fun_space(), F) tu.check_equal(dp.get_res_space(), R) fnames = extraf rnames = extrar if len(fnames) == 1: fnames = fnames[0] if len(rnames) == 1: rnames = rnames[0] # now dp has extra (1) and (1) return SimpleWrap(dp, fnames=fnames, rnames=rnames)
def flatten_add_prefix(ndp, prefix): """ Adds a prefix for every node name and to functions/resources. """ if isinstance(ndp, SimpleWrap): dp = ndp.get_dp() fnames = ['%s%s%s' % (prefix, sep, _) for _ in ndp.get_fnames()] rnames = ['%s%s%s' % (prefix, sep, _) for _ in ndp.get_rnames()] icon = ndp.icon if len(fnames) == 1: fnames = fnames[0] if len(rnames) == 1: rnames = rnames[0] sw = SimpleWrap(dp, fnames=fnames, rnames=rnames, icon=icon) return sw if isinstance(ndp, CompositeNamedDP): def get_new_name(name2): isf, fname = is_fun_node_name(name2) isr, rname = is_res_node_name(name2) if isf: return get_name_for_fun_node('%s%s%s' % (prefix, sep, fname)) elif isr: return get_name_for_res_node('%s%s%s' % (prefix, sep, rname)) else: return "%s%s%s" % (prefix, sep, name2) def transform(name2, ndp2): # Returns name, ndp isf, fname = is_fun_node_name(name2) isr, rname = is_res_node_name(name2) if isf or isr: if isinstance(ndp2, SimpleWrap): if isf: fnames = "%s%s%s" % (prefix, sep, fname) rnames = "%s%s%s" % (prefix, sep, fname) if isr: fnames = "%s%s%s" % (prefix, sep, rname) rnames = "%s%s%s" % (prefix, sep, rname) dp = ndp2.dp res = SimpleWrap(dp=dp, fnames=fnames, rnames=rnames) elif isinstance(ndp2, LabelerNDP): ndp_inside = transform(name2, ndp2.ndp) return LabelerNDP(ndp_inside, ndp2.recursive_name) else: raise NotImplementedError(type(ndp2)) else: res = flatten_add_prefix(ndp2, prefix) return res names2 = {} connections2 = set() for name2, ndp2 in ndp.get_name2ndp().items(): name_ = get_new_name(name2) ndp_ = transform(name2, ndp2) assert not name_ in names2 names2[name_] = ndp_ for c in ndp.get_connections(): dp1, s1, dp2, s2 = c.dp1, c.s1, c.dp2, c.s2 dp1 = get_new_name(dp1) dp2 = get_new_name(dp2) s1_ = "%s%s%s" % (prefix, sep, s1) s2_ = "%s%s%s" % (prefix, sep, s2) assert s1_ in names2[dp1].get_rnames(), (s1_, names2[dp1].get_rnames()) assert s2_ in names2[dp2].get_fnames(), (s2_, names2[dp1].get_fnames()) c2 = Connection(dp1=dp1, s1=s1_, dp2=dp2, s2=s2_) connections2.add(c2) fnames2 = ['%s%s%s' % (prefix, sep, _) for _ in ndp.get_fnames()] rnames2 = ['%s%s%s' % (prefix, sep, _) for _ in ndp.get_rnames()] return CompositeNamedDP.from_parts(names2, connections2, fnames2, rnames2) if isinstance(ndp, NamedDPCoproduct): children = ndp.ndps children2 = tuple([flatten_add_prefix(_, prefix) for _ in children]) labels2 = ndp.labels return NamedDPCoproduct(children2, labels2) if isinstance(ndp, LabelerNDP): x = flatten_add_prefix(ndp.ndp, prefix) return LabelerNDP(x, ndp.recursive_name) assert False, type(ndp)
def cndp_flatten(ndp): check_isinstance(ndp, CompositeNamedDP) name2ndp = ndp.get_name2ndp() connections = ndp.get_connections() fnames = ndp.get_fnames() rnames = ndp.get_rnames() names2 = {} connections2 = [] proxy_functions = defaultdict(lambda: dict()) # proxy[name][fname] proxy_resources = defaultdict(lambda: dict()) for name, n0 in name2ndp.items(): # add empty (in case they have no functions/resources) proxy_functions[name] = {} proxy_resources[name] = {} n1 = n0.flatten() if isinstance(n1, CompositeNamedDP): nn = flatten_add_prefix(n1, prefix=name) else: nn = n1 if isinstance(nn, CompositeNamedDP): # nn_connections = nn.get_connections() for name2, ndp2 in nn.get_name2ndp().items(): assert not name2 in names2 isitf, is_fname = is_fun_node_name(name2) isitr, is_rname = is_res_node_name(name2) if (isitf or isitr): # connected_to_something = is_dp_connected(name2, nn_connections) # do not add the identity nodes # that represent functions or resources # except if they are unconnected # add_identities = not connected_to_something add_identities = True if not add_identities: # pragma: no cover continue else: # think of the case where there are a f and r with # same name if isitf: use_name = is_fname + '_f' if isitr: use_name = is_rname + '_r' assert not use_name in names2, use_name names2[use_name] = ndp2 if isitf: proxy_functions[name][is_fname] = ( use_name, ndp2.get_fnames()[0]) if isitr: proxy_resources[name][is_rname] = ( use_name, ndp2.get_rnames()[0]) else: assert not name2 in names2 names2[name2] = ndp2 for c in nn.get_connections(): # is it a connection to a function if False: isitf, fn = is_fun_node_name(c.dp1) isitr, rn = is_res_node_name(c.dp2) if isitf and isitr: # This is the case where there is a straight connection # from function to resource: # # f = instance mcdp { # provides a [dimensionless] # requires c [dimensionless] # # c >= a # } # In this case, we need to add an identity new_name = '_%s_pass_through_%s' % (name, c.s2) F = nn.get_name2ndp()[c.dp1].get_ftype(c.s1) ndp_pass = SimpleWrap(Identity(F), fnames=fn, rnames=rn) assert not new_name in names2 names2[new_name] = ndp_pass proxy_functions[name][fn] = (new_name, fn) proxy_resources[name][rn] = (new_name, rn) continue if isitf: proxy_functions[name][fn] = (c.dp2, c.s2) continue if isitr: proxy_resources[name][rn] = (c.dp1, c.s1) continue isitf, fn = is_fun_node_name(c.dp1) if isitf: dp1 = fn + '_f' assert dp1 in names2 else: dp1 = c.dp1 isitr, rn = is_res_node_name(c.dp2) if isitr: dp2 = rn + '_r' assert dp2 in names2 else: dp2 = c.dp2 assert dp1 in names2 assert dp2 in names2 assert c.s1 in names2[dp1].get_rnames() assert c.s2 in names2[dp2].get_fnames() c2 = Connection(dp1=dp1, s1=c.s1, dp2=dp2, s2=c.s2) connections2.append(c2) else: for fn in nn.get_fnames(): proxy_functions[name][fn] = (name, fn) for rn in nn.get_rnames(): proxy_resources[name][rn] = (name, rn) assert not name in names2 names2[name] = nn # check that these were correctly generated: # proxy_functions # proxy_resources def exploded(name): return isinstance(name2ndp[name], CompositeNamedDP) # print list(proxy_resources) errors = [] for name, n0 in name2ndp.items(): try: assert name in proxy_functions, name assert name in proxy_resources if exploded(name): for fname in n0.get_fnames(): newfname = "%s/%s" % (name, fname) assert newfname in proxy_functions[name], ( newfname, proxy_functions[name]) for rname in n0.get_rnames(): newrname = "%s/%s" % (name, rname) assert newrname in proxy_resources[name], ( newrname, proxy_resources[name]) else: for fname in n0.get_fnames(): assert fname in proxy_functions[name], ( fname, proxy_functions[name]) for rname in n0.get_rnames(): assert rname in proxy_resources[name] except Exception as e: # pragma: no cover s = '%s:\n %s %s \n\n%s' % (name, proxy_resources[name], proxy_functions[name], e) errors.append(s) if errors: # pragma: no cover s = "\n\n".join(errors) s += '%s %s' % (proxy_resources, proxy_functions) raise Exception(s) for c in connections: dp2 = c.dp2 s2 = c.s2 dp1 = c.dp1 s1 = c.s1 dp2_was_exploded = isinstance(name2ndp[dp2], CompositeNamedDP) if dp2_was_exploded: if not dp2 in proxy_functions: # pragma: no cover msg = 'Bug: cannot find dp2.' raise_desc(DPInternalError, msg, dp2=dp2, keys=list(proxy_functions), c=c) (dp2_, s2_) = proxy_functions[dp2]["%s/%s" % (dp2, s2)] if not dp2_ in names2: # pragma: no cover raise_desc(DPInternalError, "?", dp2_=dp2_, c=c, names2=sorted(names2)) else: dp2_ = dp2 s2_ = s2 dp1_was_exploded = isinstance(name2ndp[dp1], CompositeNamedDP) if dp1_was_exploded: (dp1_, s1_) = proxy_resources[dp1]["%s/%s" % (dp1, s1)] else: dp1_ = dp1 s1_ = s1 assert dp1_ in names2 assert s1_ in names2[dp1_].get_rnames(), (s1_, names2[dp1_].get_rnames()) assert dp2_ in names2 assert s2_ in names2[dp2_].get_fnames(), (s2_, names2[dp2_].get_fnames()) c2 = Connection(dp1=dp1_, s1=s1_, dp2=dp2_, s2=s2_) connections2.append(c2) ndp_res = CompositeNamedDP.from_parts(names2, connections2, fnames, rnames) ndp_simplified = simplify_identities(ndp_res) return ndp_simplified