示例#1
0
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)
示例#2
0
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 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)
示例#4
0
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)
示例#6
0
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)
示例#7
0
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)
示例#8
0
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)
示例#9
0
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)
示例#10
0
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
示例#11
0
    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))
示例#12
0
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
示例#13
0
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
示例#14
0
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
示例#15
0
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
示例#16
0
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)
示例#17
0
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
示例#18
0
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
示例#19
0
 def get_current_ndp(self):
     return CompositeNamedDP.from_context(self.context)
示例#20
0
 def get_current_ndp(self):
     return CompositeNamedDP.from_context(self.context)