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 wrap_change_name_resource(ndp, rn, rn2): from mocdp.comp.wrap import dpwrap R = ndp.get_rtype(rn) tmpname = '__tmp_%s' % rn second = dpwrap(Identity(R), tmpname, rn2) from mocdp.comp.connection import connect2 connections = set([Connection('-', rn, '-', tmpname)]) return connect2(ndp, second, connections, split=[])
def wrap_change_name_function(ndp, fn, fn2): from mocdp.comp.wrap import dpwrap F = ndp.get_ftype(fn) tmpname = '__tmp_%s' % fn first = dpwrap(Identity(F), fn2, tmpname) from mocdp.comp.connection import connect2 connections = set([Connection('-', tmpname, '-', fn)]) return connect2(first, ndp, connections, split=[])
def reorder_functions(ndp, rnames): F = ndp.get_ftypes(rnames) ndp0 = dpwrap(Identity(F), rnames, rnames) connections = [Connection('*', fn, '*', fn) for fn in rnames] return connect2(ndp0, res, set(connections), split=[], repeated_ok=True)
def reorder_resources(ndp, rnames): R = ndp.get_rtypes(rnames) ndp2 = dpwrap(Identity(R), rnames, rnames) connections = [Connection('*', rn, '*', rn) for rn in rnames] return connect2(res, ndp2, set(connections), split=[], repeated_ok=True)
def connect_resources_to_outside(name2ndp, connections, ndp_name, rnames): """ For each function in fnames of ndp_name, create a new outside function node and connect it to ndp_name. """ assert ndp_name in name2ndp ndp = name2ndp[ndp_name] if not set(rnames).issubset(ndp.get_rnames()): msg = 'Some of the resources are not present.' raise_desc(ValueError, msg, rnames=rnames, ndp=ndp) for rn in rnames: nn = get_name_for_res_node(rn) R = ndp.get_rtype(rn) name2ndp[nn] = dpwrap(Identity(R), rn, rn) connections.append(Connection(ndp_name, rn, nn, rn))
def connect_functions_to_outside(name2ndp, connections, ndp_name, fnames): """ For each function in fnames of ndp_name, create a new outside function node and connect it to ndp_name. """ assert ndp_name in name2ndp ndp = name2ndp[ndp_name] if not set(fnames).issubset(ndp.get_fnames()): msg = 'Some of the functions are not present.' raise_desc(ValueError, msg, fnames=fnames, ndp=ndp) for fname in fnames: F = ndp.get_ftype(fname) nn = get_name_for_fun_node(fname) name2ndp[nn] = dpwrap(Identity(F), fname, fname) connections.append(Connection(nn, fname, ndp_name, fname))
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 connect2(ndp1, ndp2, connections, split, repeated_ok=False): """ Note the argument split must be a list of strings so that orders are preserved and deterministic. """ if ndp1 is ndp2: raise ValueError('Equal') def common(x, y): return len(set(x + y)) != len(set(x)) + len(set(y)) if not repeated_ok: if (common(ndp1.get_fnames(), ndp2.get_fnames()) or common(ndp1.get_rnames(), ndp2.get_rnames())): raise_desc(DPInternalError, 'repeated names', ndp1=ndp1, ndp2=ndp2, connections=connections, split=split) if len(set(split)) != len(split): msg = 'Repeated signals in split: %s' % str(split) raise ValueError(msg) try: if not connections: raise ValueError('Empty connections') # | |------------------------->A # | | |-B1(split)-----> # f1->| |--B1----->| ___ # | 1 | |----B2->| | all_s2 = B2 + C2 all_s1 = B1 + C1 # |___| -C1--C2---------->| 2 |->r2 # ---------D----------------->|___| # # ftot = f1 + D # rtot = A + b1 + r2 # A + B + C = r1 # B + C + D = f2 # split = A + B # split = B1 is given # find B2 from B1 def s2_from_s1(s1): for c in connections: if c.s1 == s1: return c.s2 assert False, 'Cannot find connection with s1 = %s' % s1 def s1_from_s2(s2): for c in connections: if c.s2 == s2: return c.s1 assert False, 'Cannot find connection with s2 = %s' % s2 f1 = ndp1.get_fnames() r1 = ndp1.get_rnames() f2 = ndp2.get_fnames() r2 = ndp2.get_rnames() all_s2 = set([c.s2 for c in connections]) all_s1 = set([c.s1 for c in connections]) # assert that all split are in s1 for x in split: assert x in all_s1 B1 = list(split) B2 = map(s2_from_s1, B1) C2 = list_diff(all_s2, B2) C1 = map(s1_from_s2, C2) A = list_diff(r1, B1 + C1) D = list_diff(f2, B2 + C2) # print('B1: %s' % B1) # print('B2: %s' % B2) # print('C2: %s' % C1) # print('C1: %s' % C1) # print(' A: %s' % A) # print(' D: %s' % D) fntot = f1 + D rntot = A + B1 + r2 if there_are_repetitions(fntot) or there_are_repetitions(rntot): raise_desc(NotImplementedError, 'Repeated names', fnames=fntot, rnames=fntot) # now I can create Ftot and Rtot f1_types = ndp1.get_ftypes(f1) D_types = ndp2.get_ftypes(D) # print('f1: %s' % f1) # print('f1 types: %s' % f1_types) # print('D: %s' % D) # print('D types: %s' % D_types) Ftot = PosetProduct(tuple(list(f1_types) + list(D_types))) Rtot = PosetProduct( tuple( list(ndp1.get_rtypes(A)) + list(ndp1.get_rtypes(B1)) + list(ndp2.get_rtypes(r2)))) # print('Ftot: %s' % str(Ftot)) # print(' %s' % str(fntot)) # print('Rtot: %s' % str(Rtot)) # print(' %s' % str(rntot)) assert len(fntot) == len(Ftot), (fntot, Ftot) assert len(rntot) == len(Rtot), (rntot, Rtot) # I can create the first muxer m1 # from ftot to Product(f1, D) m1_for_f1 = [fntot.index(s) for s in f1] m1_for_D = [fntot.index(s) for s in D] m1coords = [m1_for_f1, m1_for_D] m1 = Mux(Ftot, m1coords) # print('m1: %s' % m1) # print('m1.R: %s' % m1.get_res_space()) # Get Identity on D D_types = ndp2.get_ftypes(D) Id_D = Identity(D_types) ndp1_p = its_dp_as_product(ndp1) X = make_parallel(ndp1_p, Id_D) # make sure we can connect m1_X = make_series(m1, X) # print('m1_X = %s' % m1_X) # print('m1_X.R = %s' % m1_X.get_res_space() ) def coords_cat(c1, m): if m != (): return c1 + (m, ) else: return c1 A_B1_types = PosetProduct( tuple(ndp1.get_rtypes(A)) + tuple(ndp1.get_rtypes(B1))) Id_A_B1 = Identity(A_B1_types) ndp2_p = its_dp_as_product(ndp2) Z = make_parallel(Id_A_B1, ndp2_p) # print('Z.R = %s' % Z.get_res_space()) # print('B1: %s' % B1) # print('R2: %s' % r2) m2coords_A = [(0, (A + B1).index(x)) for x in A] m2coords_B1 = [(0, (A + B1).index(x)) for x in B1] m2coords_r2 = [(1, r2.index(x)) for x in r2] m2coords = m2coords_A + m2coords_B1 + m2coords_r2 # print('m2coords_A: %r' % m2coords_A) # print('m2coords_B1: %r' % m2coords_B1) # print('m2coords_r2: %r' % m2coords_r2) # print('m2coords: %r' % m2coords) # print('Z.R: %s' % Z.get_res_space()) m2 = Mux(Z.get_res_space(), m2coords) assert len(m2.get_res_space()) == len(rntot), ((m2.get_res_space(), rntot)) # make sure we can connect make_series(Z, m2) # # f0 -> |m1| -> | X | -> |Y |-> |Z| -> |m2| -> r0 # # X = dp1 | Id_D # Z = Id_B1 | dp2 # ___ # | |------------------------->A # | | |-B1-----------> # f1->| |--B1----->| ___ # | 1 | |----B2->| | # |___| -C1-----------C2->| 2 |->r2 # ---------D----------------->|___| # ___ # | |-------------------------------->A # | | . *-B1-------.-----> # f1->| | . |--B1----->* . ___ # | 1 |--.-| *----B2->| . | | # |___| . |-C1------------C2->|-.->| 2 |->r2 # ---------D-.-------------------->| . |___| # m1 | X | Y | Z | m2 # I need to write the muxer # look at the end # iterate 2's functions Y_coords_A_B1 = [] for x in A: Y_coords_A_B1.append((0, r1.index(x))) for x in B1: Y_coords_A_B1.append((0, r1.index(x))) Y_coords_B2_C2_D = [] for x in f2: if (x in B2) or (x in C2): Y_coords_B2_C2_D.append((0, r1.index(s1_from_s2(x)))) assert x not in D elif x in D: Y_coords_B2_C2_D.append((1, D.index(x))) else: assert False # print ('Y_coords_A_B1: %s' % Y_coords_A_B1) # print ('Y_coords_B2_C2_D: %s' % Y_coords_B2_C2_D) Y_coords = [Y_coords_A_B1, Y_coords_B2_C2_D] Y = Mux(m1_X.get_res_space(), Y_coords) # m1* Xp Y* Zp m2* # Let's make series # m1_X is simplifed Y_Z = make_series(Y, Z) Y_Z_m2 = make_series(Y_Z, m2) res_dp = make_series(m1_X, Y_Z_m2) fnames = fntot rnames = rntot res_dp, fnames, rnames = simplify_if_only_one_name( res_dp, fnames, rnames) # print('res_dp: %s' % res_dp) res = dpwrap(res_dp, fnames, rnames) return res except Exception as e: msg = 'connect2() failed' raise_wrapped(DPInternalError, e, msg, ndp1=ndp1, ndp2=ndp2, connections=connections, split=split)
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 Identity1(): F = parse_poset('V') return Identity(F)
def get_primitivedp(): from mcdp_dp import Identity from mcdp_posets import Nat return Identity(Nat()) #mcdp_primitive