예제 #1
0
def lcm_list( xs ):
    l = 1
    for x in xs:
        l = lcm( l, x )
    return l
예제 #2
0
    def add_edge(self, u, v, attr_dict=None, **attr):
        assert attr_dict is None, "FIXME: add_edge does not deal with attr_dict"

        production = attr['production'] = SDFGraph.validate_vector(
            (u, v), attr.get('production', 1), 'production rate')
        assert type(production) is Cyclic

        # update phases
        try:
            phases_u = self.nodes[u].get('phases', 1)
            self.nodes[u]['phases'] = lcm(len(production), phases_u)
        except KeyError:
            super().add_node(u,
                             wcet=Cyclic(0),
                             phases=len(production),
                             period=1)

        consumption = attr['consumption'] = SDFGraph.validate_vector(
            (u, v), attr.get('consumption', 1), 'consumption rates')
        assert type(consumption) is Cyclic

        # update phases
        try:
            phases_v = self.nodes[v].get('phases', 1)
            self.nodes[v]['phases'] = lcm(len(consumption), phases_v)
        except KeyError:
            super().add_node(v,
                             wcet=Cyclic(0),
                             phases=len(consumption),
                             period=1)

        try:
            tokens = int(attr.get('tokens', 0))
            assert tokens >= 0
            attr['tokens'] = tokens
        except ValueError:
            raise SDFParseError(
                "Channel {} has an invalid number of tokens: {}".format(
                    (u, v), attr['tokens']))

        if (self.has_edge(u, v)):
            # FIXME: replace parallel edges by single edge
            # insert auxilary node

            pr = attr.get('production')
            cr = attr.get('consumption')
            toks = attr.get('tokens')

            aux, c = "aux_0", 0
            while aux in self.nodes:
                c += 1
                aux = "aux_{}".format(c)

            self.add_node(aux, wcet=0)
            self.add_edge(u, aux, production=pr, consumption=1, tokens=toks)
            self.add_edge(aux, v, production=1, consumption=cr)
            print("WARNING: added node {} to prevent parallel edge ({}, {})".
                  format(aux, u, v))
        else:
            super().add_edge(u, v, attr_dict, **attr)

        if 'capacity' in attr:
            try:
                capacity = int(attr['capacity'])
                if capacity < tokens:
                    raise Exception(
                        "Tokens on channel {} violates specified capacity".
                        format((u, v)))

                del self.get_edge_data(u, v)['capacity']

                # create reverse channel (w, v)
                self.add_edge(v,
                              u,
                              production=attr['consumption'],
                              consumption=attr['production'],
                              tokens=capacity - tokens)

            except ValueError:
                del self.get_edge_data(u, v)['capacity']

                # create reverse channel (w, v)
                self.add_edge(v,
                              u,
                              production=attr['consumption'],
                              consumption=attr['production'],
                              var=attr['capacity'])
예제 #3
0
    def __check_consistency(self):
        node_lcm_rates = {}

        for v, w, data in self.edges(data=True):
            prates = data.get('production')
            crates = data.get('consumption')

            if prates.sum() <= 0 or len(prates) == 0:
                raise Exception(
                    "({}, {}) has an invalid production rate vector (sum = {})"
                    .format(v, w, prates.sum()))

            if crates.sum() <= 0 or len(crates) == 0:
                raise Exception(
                    "({}, {}) has an invalid consumption rate vector (sum = {})"
                    .format(v, w, crates.sum()))

            avg_prate = Fraction(prates.sum(), len(prates))
            avg_crate = Fraction(crates.sum(), len(crates))

            node_lcm_rates[v] = lcm(
                lcm(node_lcm_rates.get(v, 1), prates.sum()),
                avg_prate.denominator)
            if node_lcm_rates[v] == 0:
                raise Exception(
                    "LCM of rates associated with actor {} is zero", v)

            node_lcm_rates[w] = lcm(
                lcm(node_lcm_rates.get(w, 1), crates.sum()),
                avg_crate.denominator)
            if node_lcm_rates[w] == 0:
                raise Exception(
                    "LCM of rates associated with actor {} is zero", w)

        fractional_q = {}
        undirected = self.to_undirected()
        for v, w, key in dfs_edges(undirected):
            # if self does not cantain (v, w), it must contains (w, v)
            if not self.has_edge(v, w, key):
                v, w = w, v

            # get rates of channel (v, w)
            data = self.get_edge_data(v, w, key)
            p_vw, c_vw = data.get('production'), data.get('consumption')
            v_period = self.nodes[v]['period']
            w_period = self.nodes[w]['period']

            # if there is an edge (w, v) in sdfg, check whether it's consistent with (v, w)
            if v != w and self.has_edge(w, v):
                data_reverse = self.get_edge_data(w, v, 0)
                p_wv, c_wv = data_reverse.get('production'), data_reverse.get(
                    'consumption')
                if p_vw.sum(0, v_period) * p_wv.sum(0, w_period) != c_vw.sum(
                        0, w_period) * c_wv.sum(0, v_period):
                    raise Exception("Inconsistent cycle: [{},{},{}]".format(
                        v, w, v))

            # check consistency of (v, w) with rest of the self
            if (v in fractional_q) and (w in fractional_q):
                if p_vw.sum(0, v_period) * fractional_q[v] != c_vw.sum(
                        0, w_period) * fractional_q[w]:
                    raise Exception("Inconsistent edge: ({},{})".format(v, w))

            elif (v in fractional_q):
                fractional_q[w] = fractional_q[v] * Fraction(
                    p_vw.sum(0, v_period), c_vw.sum(0, w_period))

            elif (w in fractional_q):
                fractional_q[v] = fractional_q[w] * Fraction(
                    c_vw.sum(0, w_period), p_vw.sum(0, v_period))

            else:
                fractional_q[v] = 1
                fractional_q[w] = Fraction(p_vw.sum(0, v_period),
                                           c_vw.sum(0, w_period))

        # compute the LCM of the denominators in the fractional repetition vector
        m = 1
        for f in fractional_q.values():
            m = lcm(m, Fraction(f).denominator)

        # multiply all fractions with the LCM of their denominators to obtain the repetition vector
        q = {}
        tpi = 1
        for k in fractional_q:
            f = fractional_q[k]
            q[k] = int(f * m * self.phases(k))
            assert (node_lcm_rates[k] * f * m).denominator == 1
            tpi = lcm(tpi, (node_lcm_rates[k] * f * m).numerator)

        s = {}
        for v, w, data in self.edges(data=True):
            prate, crate = data.get('production'), data.get('consumption')
            s[(v, w)] = (tpi * len(prate)) // (q[v] * prate.sum())

        return q, s, tpi
예제 #4
0
    def __build(self, graph):
        for v, data in graph.nodes(data=True):
            wcet = SDFGraph.__validate_vector(v, data.get('wcet', 0), 'wcet')
            super().add_node(v, wcet=wcet, phases=len(wcet))

        for u, v, data in graph.edges(data=True):
            production = SDFGraph.__validate_vector((u, v),
                                                    data.get('production', 1),
                                                    'production rate')
            consumption = SDFGraph.__validate_vector(
                (u, v), data.get('consumption', 1), 'consumption rates')
            g_uv = gcd(production.sum(), consumption.sum())

            try:
                tokens = int(data.get('tokens', 0))
            except ValueError:
                raise SDFParseError(
                    "Channel {} has an invalid token specification: {}".format(
                        (u, v), data['tokens']))

            super().add_edge(u,
                             v,
                             production=production,
                             consumption=consumption,
                             tokens=tokens,
                             gcd=g_uv,
                             pred=SDFGraph.__predecessor_fun(
                                 production, consumption, tokens))

            if 'capacity' in data:
                try:
                    capacity = int(data['capacity'])
                    if capacity < tokens:
                        raise Exception(
                            "More tokens on channel {} than specified capacity"
                            .format((u, v)))

                    # create reverse channel (w, v)
                    super().add_edge(v,
                                     u,
                                     production=consumption,
                                     consumption=production,
                                     tokens=capacity - tokens,
                                     gcd=g_uv,
                                     pred=SDFGraph.__predecessor_fun(
                                         consumption, production,
                                         capacity - tokens))
                    # succ = SDFGraph.__successor_fun( consumption, production, capacity - tokens ))

                except ValueError:
                    # create reverse channel (w, v)
                    raise SDFParseError(
                        "Channel {} has an invalid capacity specification: {}".
                        format((u, v), data['capacity']))

        # update phases
        for v, data in self.nodes(data=True):
            phases = data['phases']
            for u, _, edge_data in self.in_edges(v, True):
                phases = lcm(phases, len(edge_data['consumption']))

            for _, w, edge_data in self.out_edges(v, True):
                phases = lcm(phases, len(edge_data['production']))

            data['period'] = data['phases'] = phases