def make_approximation_f(name, approx_perc, approx_abs, approx_abs_S, max_value, max_value_S, ndp): F = ndp.get_ftype(name) ndp_before = get_approx_dp(F, name, approx_perc, approx_abs, approx_abs_S, max_value, max_value_S) name2ndp = {NAME_ORIGINAL: ndp, NAME_APPROX: ndp_before} fnames = ndp.get_fnames() rnames = ndp.get_rnames() connections = [] connections.append(Connection(NAME_APPROX, name, NAME_ORIGINAL, name)) for fn in fnames: F = ndp.get_ftype(fn) fn_ndp = dpwrap(Identity(F), fn, fn) fn_name = get_name_for_fun_node(fn) name2ndp[fn_name] = fn_ndp if fn == name: connections.append(Connection(fn_name, fn, NAME_APPROX, fn)) else: connections.append(Connection(fn_name, fn, NAME_ORIGINAL, fn)) for rn in rnames: R = ndp.get_rtype(rn) rn_ndp = dpwrap(Identity(R), rn, rn) rn_name = get_name_for_res_node(rn) name2ndp[rn_name] = rn_ndp connections.append(Connection(NAME_ORIGINAL, rn, rn_name, rn)) return CompositeNamedDP.from_parts(name2ndp, connections, fnames, rnames)
def cndp_sub(cndp, nodes_i): """ Returns a subset of the CompositeNamedDP with only certain nodes. """ name2ndp = cndp.get_name2ndp() for n in nodes_i: assert n in name2ndp connections = cndp.get_connections() fnames = cndp.get_fnames() rnames = cndp.get_rnames() name2ndp_i = dict((k, v) for k, v in name2ndp.items() if k in nodes_i) filter_c = lambda c: c.involves_any_of_these_nodes(nodes_i) connections_i = filter(filter_c, connections) def filter_function(fn): for ndp in name2ndp_i.values(): if fn in ndp.get_fnames(): return True return False def filter_resource(rn): for ndp in name2ndp_i.values(): if rn in ndp.get_rnames(): return True return False fnames_i = filter(filter_function, fnames) rnames_i = filter(filter_resource, rnames) ndp_i = CompositeNamedDP.from_parts(name2ndp=name2ndp_i, connections=connections_i, fnames=fnames_i, rnames=rnames_i) return ndp_i
def cndp_remove_one_child(cndp, to_remove): """ Removes a child from NDP. Assumes ndp connected. Dangling arrows are substituted with top/bottom. """ print('removing %r' % to_remove) cndp.check_fully_connected() name2ndp = cndp.get_name2ndp() assert to_remove in name2ndp connections = cndp.get_connections() fnames = cndp.get_fnames() rnames = cndp.get_rnames() name2ndp_i = dict((k, v) for k, v in name2ndp.items() if k != to_remove) filter_c = lambda c: not c.involves_any_of_these_nodes([to_remove]) connections_i = filter(filter_c, connections) ndp2 = CompositeNamedDP.from_parts(name2ndp=name2ndp_i, connections=connections_i, fnames=fnames, rnames=rnames) unconnected_fun, unconnected_res = get_missing_connections(ndp2.context) for r in [CResource(*_) for _ in unconnected_res]: R = ndp2.context.get_rtype(r) values = R.get_maximal_elements() dp = LimitMaximals(R, values) new_ndp = dpwrap(dp, 'limit', []) name = ndp2.context.new_name('_limit_r') ndp2.context.add_ndp(name, new_ndp) c = Connection(dp2=name, s2='limit', dp1=r.dp, s1=r.s) ndp2.context.add_connection(c) for f in [CFunction(*_) for _ in unconnected_fun]: F = ndp2.context.get_ftype(f) values = F.get_minimal_elements() dp = ConstantMinimals(F, values) new_ndp = dpwrap(dp, [], 'limit') name = ndp2.context.new_name('_limit_f') ndp2.context.add_ndp(name, new_ndp) c = Connection(dp1=name, s1='limit', dp2=f.dp, s2=f.s) ndp2.context.add_connection(c) ndp2.check_fully_connected() return ndp2
def cndp_create_one_without_some_connections(ndp, exclude_connections, names): """ Creates a new CompositeNDP without some of the connections. A new function / resource pair is created for each cut connection. """ from mocdp.comp.context import Context context = Context() # Create the fun/res node in the original order for fname in ndp.get_fnames(): # simply copy the functionnode - it might be a LabeledNDP name = get_name_for_fun_node(fname) fndp = ndp.get_name2ndp()[name] context.fnames.append(fname) context.add_ndp(name, fndp) for rname in ndp.get_rnames(): # simply copy the functionnode - it might be a LabeledNDP name = get_name_for_res_node(rname) rndp = ndp.get_name2ndp()[name] context.rnames.append(rname) context.add_ndp(name, rndp) for _name, _ndp in ndp.get_name2ndp().items(): isf, fname = is_fun_node_name(_name) isr, rname = is_res_node_name(_name) if isf and fname in ndp.get_fnames(): pass elif isr and rname in ndp.get_rnames(): pass else: # print('regular: %r' % _name) context.add_ndp(_name, _ndp) for c in ndp.get_connections(): if c in exclude_connections: continue # print('adding connection %s' % str(c)) context.connections.append(c) # print('done') # for each cut connection for e, name in zip(exclude_connections, names): S = context.get_rtype(CResource(e.dp1, e.s1)) fn = context.add_ndp_fun_node(name, S) rn = context.add_ndp_res_node(name, S) c1 = Connection(e.dp1, e.s1, rn, name) c2 = Connection(fn, name, e.dp2, e.s2) context.connections.append(c1) context.connections.append(c2) return CompositeNamedDP.from_context(context)
def ignore_some(ndp, ignore_fnames, ignore_rnames): """ Ignores some functionalities or resources """ fnames0 = ndp.get_fnames() rnames0 = ndp.get_rnames() for fname in ignore_fnames: check_isinstance(fname, str) if not fname in fnames0: msg = 'Could not find functionality %r in %r.' % (fname, fnames0) raise_desc(ValueError, msg, fname=fname, fnames=fnames0) for rname in ignore_rnames: check_isinstance(rname, str) if not rname in rnames0: msg = 'Could not find resource %r in %r.' % (rname, rnames0) raise_desc(ValueError, msg, rname=rname, rnames=rnames0) c = Context() orig = '_orig' c.add_ndp(orig, ndp) for fname in ndp.get_fnames(): F = ndp.get_ftype(fname) if fname in ignore_fnames: dp = Constant(F, F.get_bottom()) n = '_const_f_%s' % fname c.add_ndp(n, dpwrap(dp, [], fname)) else: n = c.add_ndp_fun_node(fname, F) con = Connection(n, fname, orig, fname) c.add_connection(con) for rname in ndp.get_rnames(): R = ndp.get_rtype(rname) if rname in ignore_rnames: dp = LimitMaximals(R, R.get_maximal_elements()) n = '_const_r_%s' % rname c.add_ndp(n, dpwrap(dp, rname, [])) else: n = c.add_ndp_res_node(rname, R) con = Connection(orig, rname, n, rname) c.add_connection(con) return CompositeNamedDP.from_context(c)
def cndp_templatize_children(cndp): """ Replaces all sub composites with the corresponding template """ assert isinstance(cndp, CompositeNamedDP), cndp fnames = cndp.get_fnames() rnames = cndp.get_rnames() connections = cndp.get_connections() def filter_child(child): if isinstance(child, CompositeNamedDP): return ndp_templatize(child, mark_as_template=False) elif isinstance(child, NamedDPCoproduct): return ndpcoproduct_templatize(child) else: return child name2ndp = dict([(k, filter_child(v)) for k, v in cndp.get_name2ndp().items()]) return CompositeNamedDP.from_parts(name2ndp, connections, fnames, rnames)
def get_lower_bound_ndp(context): """ We create an NDP where each open resource becomes a new resource. and all the functions are given a lower bound of 0. The new resources are given a name like: dummy<i> """ context = clone_context(context) unconnected_fun, unconnected_res = get_missing_connections(context) # let's remove the new resources that are unconnected for rname, name, _ndp in context.iterate_new_resources(): if (name, rname) in unconnected_fun: unconnected_fun.remove((name, rname)) del context.names[name] context.rnames.remove(rname) # create a new resource for each unconnected resource resource2var = {} # CResource -> str for dp, s in unconnected_res: r = CResource(dp, s) R = context.get_rtype(r) rname = 'dummy%d' % len(resource2var) context.add_ndp_res_node(rname, R) c = Connection(dp1=dp, s1=s, dp2=get_name_for_res_node(rname), s2=rname) context.add_connection(c) resource2var[r] = rname # add a minimal bound for all unconnected functions for dp, s in unconnected_fun: f = CFunction(dp, s) F = context.get_ftype(f) minimals = F.get_minimal_elements() res = get_constant_minimals_as_resources(F, minimals, context) c = Connection(dp1=res.dp, s1=res.s, dp2=dp, s2=s) context.add_connection(c) ndp = CompositeNamedDP.from_context(context) ndp.check_fully_connected() return ndp, resource2var
def visit(recname, ndp): if isinstance(ndp, CompositeNamedDP): # NOTE: Does not label CompositeNamedDP context = Context() for child_name, child_ndp in ndp.get_name2ndp().items(): child_ndp2 = visit(recname + (child_name, ), child_ndp) context.add_ndp(child_name, child_ndp2) for c in ndp.get_connections(): context.add_connection(c) context.fnames = ndp.get_fnames() context.rnames = ndp.get_rnames() res = CompositeNamedDP.from_context(context) return res # res2 = LabelerNDP(res, recname) # return res2 elif isinstance(ndp, SimpleWrap): ndp2 = LabelerNDP(ndp, recname) return ndp2 elif isinstance(ndp, NamedDPCoproduct): assert len(ndp.ndps) == len(ndp.labels), ndp children = [] labels = [] for child_ndp, child_label in zip(ndp.ndps, ndp.labels): child2 = visit(recname + (child_label, ), child_ndp) children.append(child2) labels.append(child_label) res = NamedDPCoproduct(tuple(children), tuple(labels)) res2 = LabelerNDP(res, recname) return res2 elif isinstance(ndp, LabelerNDP): msg = 'Trying to re-label this as {}'.format(recname) raise_desc(DPInternalError, msg, ndp=ndp) else: raise NotImplementedError(type(ndp))
def cndp_makecanonical(ndp, name_inner_muxed="_inner_muxed", s_muxed="_muxed"): """ Returns a composite with only one ndp, called <named_inner_muxed>. If there were cycles, then this will also have a signal caled s_muxed and there will be one connection to it. raises DPSemanticErrorNotConnected """ assert isinstance(ndp, CompositeNamedDP), type(ndp) try: ndp.check_fully_connected() except NotConnected as e: msg = "Cannot put in canonical form because not all subproblems are connected." raise_wrapped(DPSemanticErrorNotConnected, e, msg, compact=True) fnames = ndp.get_fnames() rnames = ndp.get_rnames() # First, we flatten it ndp = cndp_flatten(ndp) assert ndp.get_fnames() == fnames assert ndp.get_rnames() == rnames # then we compact it (take the product of edges) # Note also that this abstract() the children; # however, because we flattened before, this is redundant, # as every DP is a SimpleDP ndp = ndp.compact() assert ndp.get_fnames() == fnames assert ndp.get_rnames() == rnames # Check that we have some cycles G = get_connection_multigraph(ndp.get_connections()) cycles = list(simple_cycles(G)) if not cycles: ndp_inner = ndp cycles_names = [] else: # then we choose which edges to remove connections_to_cut = choose_connections_to_cut(connections=ndp.get_connections(), name2dp=ndp.get_name2ndp()) connections_to_cut = list(connections_to_cut) n = len(connections_to_cut) cycles_names = list(["cut%d" % _ for _ in range(n)]) ndp_inner = cndp_create_one_without_some_connections(ndp, connections_to_cut, cycles_names) assert ndp_inner.get_fnames() == fnames + cycles_names assert ndp_inner.get_rnames() == rnames + cycles_names if cycles_names: ndp_inner_muxed = add_muxes(ndp_inner, cs=cycles_names, s_muxed=s_muxed) mux_signal = s_muxed assert ndp_inner_muxed.get_fnames() == fnames + [mux_signal] assert ndp_inner_muxed.get_rnames() == rnames + [mux_signal] else: ndp_inner_muxed = ndp_inner name2ndp = {} name2ndp[name_inner_muxed] = ndp_inner_muxed connections = [] connect_functions_to_outside(name2ndp, connections, ndp_name=name_inner_muxed, fnames=fnames) connect_resources_to_outside(name2ndp, connections, ndp_name=name_inner_muxed, rnames=rnames) if cycles_names: connections.append(Connection(name_inner_muxed, mux_signal, name_inner_muxed, mux_signal)) outer = CompositeNamedDP.from_parts(name2ndp=name2ndp, connections=connections, fnames=fnames, rnames=rnames) return outer
def cndp_makecanonical(ndp, name_inner_muxed='_inner_muxed', s_muxed='_muxed'): """ Returns a composite with only one ndp, called <named_inner_muxed>. If there were cycles, then this will also have a signal caled s_muxed and there will be one connection to it. raises DPSemanticErrorNotConnected """ assert isinstance(ndp, CompositeNamedDP), type(ndp) try: ndp.check_fully_connected() except NotConnected as e: msg = 'Cannot put in canonical form because not all subproblems are connected.' raise_wrapped(DPSemanticErrorNotConnected, e, msg, compact=True) fnames = ndp.get_fnames() rnames = ndp.get_rnames() # First, we flatten it ndp = cndp_flatten(ndp) assert ndp.get_fnames() == fnames assert ndp.get_rnames() == rnames # then we compact it (take the product of edges) # Note also that this abstract() the children; # however, because we flattened before, this is redundant, # as every DP is a SimpleDP ndp = ndp.compact() assert ndp.get_fnames() == fnames assert ndp.get_rnames() == rnames # Check that we have some cycles G = get_connection_multigraph(ndp.get_connections()) cycles = list(simple_cycles(G)) if not cycles: ndp_inner = ndp cycles_names = [] else: # then we choose which edges to remove connections_to_cut = choose_connections_to_cut( connections=ndp.get_connections(), name2dp=ndp.get_name2ndp()) connections_to_cut = list(connections_to_cut) n = len(connections_to_cut) cycles_names = list(['cut%d' % _ for _ in range(n)]) ndp_inner = cndp_create_one_without_some_connections( ndp, connections_to_cut, cycles_names) assert ndp_inner.get_fnames() == fnames + cycles_names assert ndp_inner.get_rnames() == rnames + cycles_names if cycles_names: ndp_inner_muxed = add_muxes(ndp_inner, cs=cycles_names, s_muxed=s_muxed) mux_signal = s_muxed assert ndp_inner_muxed.get_fnames() == fnames + [mux_signal] assert ndp_inner_muxed.get_rnames() == rnames + [mux_signal] else: ndp_inner_muxed = ndp_inner name2ndp = {} name2ndp[name_inner_muxed] = ndp_inner_muxed connections = [] connect_functions_to_outside(name2ndp, connections, ndp_name=name_inner_muxed, fnames=fnames) connect_resources_to_outside(name2ndp, connections, ndp_name=name_inner_muxed, rnames=rnames) if cycles_names: connections.append( Connection(name_inner_muxed, mux_signal, name_inner_muxed, mux_signal)) outer = CompositeNamedDP.from_parts(name2ndp=name2ndp, connections=connections, fnames=fnames, rnames=rnames) return outer
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_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
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 dpgraph_making_sure_no_reps(context): from mocdp.comp.connection import dpgraph # functionname -> list of names that use it functions = defaultdict(lambda: list()) resources = defaultdict(lambda: list()) for fname, name, ndp in context.iterate_new_functions(): assert fname == ndp.get_fnames()[0] functions[fname].append(name) for rname, name, ndp in context.iterate_new_resources(): assert rname == ndp.get_rnames()[0] resources[rname].append(name) for name, ndp in context.names.items(): if context.is_new_function(name): continue for fn in ndp.get_fnames(): if len(functions[fn]) != 0: # print('need to translate F (%s, %s) because already in %s' % # (name, fn, functions[fn])) fn2 = '_%s_%s' % (name, fn) return dpgraph_translate_fn(context, name, fn, fn2) functions[fn].append(name) for name, ndp in context.names.items(): if context.is_new_resource(name): continue for rn in ndp.get_rnames(): if len(resources[rn]) != 0: # print('need to translate R (%s, %s) because already in %s' % # (name, rn, resources[rn])) rn2 = '_%s_%s' % (name, rn) return dpgraph_translate_rn(context, name, rn, rn2) resources[rn].append(name) name2npd = context.names connections = context.connections fnames = context.fnames rnames = context.rnames # check if there are disconnected components cndp = CompositeNamedDP.from_context(context) n = cndp_num_connected_components(cndp) if n == 1: # This is the base case res0 = dpgraph(name2npd, connections, split=[]) res = make_sure_order_functions_and_resources(res0, fnames, rnames) return res else: # This is the more complicated case cndp_list = cndp_split_in_components(cndp) assert len(cndp_list) == n # Now call each one in turn simple_wraps = [] for cndp in cndp_list: dpi = cndp_dpgraph(cndp) assert isinstance(dpi, SimpleWrap) simple_wraps.append(dpi) final = ndps_parallel(simple_wraps) res = make_sure_order_functions_and_resources(final, fnames, rnames) assert isinstance(res, SimpleWrap), type(res) return res
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 get_current_ndp(self): return CompositeNamedDP.from_context(self.context)