Exemplo n.º 1
0
    def create_graph(self, filename='graph'):
        if self.log is None:
            print(
                "ERROR: Read log file and build model before creating graph.")
            return
        elif self.TL_set is None:
            print("ERROR: Build model before creating graph.")
            return
        causality = self.causalities_dict
        parallel_events = self.parallel_tasks_set
        inv_causality = self.inv_causalities_dict
        '''
        Code below is copied from this site: https://ai.ia.agh.edu.pl/pl:dydaktyka:dss:lab03
        However some modifications were made.
        '''

        G = MyGraph()

        # adding split gateways based on causality
        for event in causality.keys():
            if len(causality[event]) > 1:
                if tuple(causality[event]) in parallel_events:
                    G.add_and_split_gateway(event, causality[event])
                else:
                    G.add_xor_split_gateway(event, causality[event])

        # adding merge gateways based on inverted causality
        for event in inv_causality.keys():
            if len(inv_causality[event]) > 1:
                if tuple(inv_causality[event]) in parallel_events:
                    G.add_and_merge_gateway(inv_causality[event], event)
                else:
                    G.add_xor_merge_gateway(inv_causality[event], event)
            elif len(inv_causality[event]) == 1:
                source = list(inv_causality[event])[0]
                G.edge(source, event)

        # adding start event
        G.add_event("start")
        if len(self.TI_set) > 1:
            if tuple(self.TI_set) in parallel_events:
                G.add_and_split_gateway("start", self.TI_set)
            else:
                G.add_xor_split_gateway("start", self.TI_set)
        else:
            G.edge("start", list(self.TI_set)[0])

        # adding end event
        G.add_event("end")
        if len(self.TO_set) > 1:
            if tuple(self.TO_set) in parallel_events:
                G.add_and_merge_gateway(self.TO_set, "end")
            else:
                G.add_xor_merge_gateway(self.TO_set, "end")
        else:
            G.edge(list(self.TO_set)[0], "end")

        # G.format = 'svg'
        G.render('graphs/' + filename)
        G.view('graphs/' + filename)
Exemplo n.º 2
0
    def create_graph(self, filename='graph'):
        G = MyGraph()
        causality = self.causality
        parallel_events = self.parallel_events
        inv_causality = self.inv_causality
        start_set_events = self.start_events
        end_set_events = self.end_events

        # adding split gateways based on causality
        for event in causality:
            if len(causality[event]) > 1:
                if tuple(causality[event]) in parallel_events:
                    G.add_and_split_gateway(event, causality[event])
                else:
                    G.add_xor_split_gateway(event, causality[event])

        # adding merge gateways based on inverted causality
        for event in inv_causality:
            if len(inv_causality[event]) > 1:
                if tuple(inv_causality[event]) in parallel_events:
                    G.add_and_merge_gateway(inv_causality[event], event)
                else:
                    G.add_xor_merge_gateway(inv_causality[event], event)
            elif len(inv_causality[event]) == 1:
                source = list(inv_causality[event])[0]
                G.edge(source, event)

        # adding start event
        G.add_event("start")
        if len(start_set_events) > 1:
            if tuple(start_set_events) in parallel_events:
                G.add_and_split_gateway(event, start_set_events)
            else:
                G.add_xor_split_gateway(event, start_set_events)
        else:
            G.edge("start", list(start_set_events)[0])

        # adding end event
        G.add_event("end")
        if len(end_set_events) > 1:
            if tuple(end_set_events) in parallel_events:
                G.add_and_merge_gateway(end_set_events, event)
            else:
                G.add_xor_merge_gateway(end_set_events, event)
        else:
            G.edge(list(end_set_events)[0], "end")

        G.render('../graphs/' + filename, view=True)
class Alpha():
    def __init__(self, log, splines='ortho'):
        self.log = log
        self.tl = self.get_TL_set()  # all tasks in the log
        self.ti = self.get_TI_set(
        )  # tasks that appear at least once as first task of a case
        self.to = self.get_TO_set(
        )  # tasks that appear at least once as last task in a case
        self.ds = self.direct_succession()  # direct successors a > b
        self.cs = self.causality()  # causality a -> b <=> a > b and b /> a
        self.pr = self.parallel()  # parralelism a > b and b > a
        self.ind = self.choice()  # no direct succession a # b and b # a
        self.xl = self.get_XL_set(
        )  # potential task connections (a->b or a->(b#c) or (b#c)->d)
        self.yl = self.get_YL_set(
        )  # subset of XL: eliminating a->b and a->c if there exists some a->(b#c), eliminating b->c and b->d if there exists some (b#c)->d.
        self.G = MyGraph(splines)
        self.inv_cs = self.inv_causality()  # inverse causality

    def __str__(self):
        alpha_sets = []
        alpha_sets.append("TL set: {}".format(self.tl))
        alpha_sets.append("TI set: {}".format(self.ti))
        alpha_sets.append("TO set: {}".format(self.to))
        alpha_sets.append("XL set: {}".format(self.xl))
        alpha_sets.append("YL set: {}".format(self.yl))
        return '\n'.join(alpha_sets)

    def get_TL_set(self):
        tl = set()
        for item in self.log:
            for i in item:
                tl.add(i)
        return tl

    def get_TI_set(self):
        ti = set()
        for item in self.log:
            ti.add(item[0])
        return ti

    def get_TO_set(self):
        to = set()
        for item in self.log:
            to.add(item[-1])
        return to

    def get_XL_set(self):
        xl = set()
        subsets = itertools.chain.from_iterable(
            itertools.combinations(self.tl, r)
            for r in range(1,
                           len(self.tl) + 1))
        independent_a_or_b = [
            a_or_b for a_or_b in subsets
            if self.__is_ind_set(a_or_b, self.ind)
        ]
        for a, b in itertools.product(independent_a_or_b, independent_a_or_b):
            if self.__is_cs_set((a, b), self.cs):
                xl.add((a, b))
        return xl

    def __is_ind_set(self, s, ind):
        if len(s) == 1:
            return True
        else:
            s_all = itertools.combinations(s, 2)
            for pair in s_all:
                if pair not in ind:
                    return False
            return True

    def __is_cs_set(self, s, cs):
        set_a, set_b = s[0], s[1]
        s_all = itertools.product(set_a, set_b)
        for pair in s_all:
            if pair not in cs:
                return False
        return True

    def get_YL_set(self):
        yl = copy.deepcopy(self.xl)
        s_all = itertools.combinations(yl, 2)
        for pair in s_all:
            if self.__issubset(pair[0], pair[1]):
                yl.discard(pair[0])
            elif self.__issubset(pair[1], pair[0]):
                yl.discard(pair[1])

        # remove self-loops
        self_loop = set()
        for pair in self.pr:
            if pair == pair[::
                            -1]:  # if we found pairs like (b,b), add b into self-loop sets
                self_loop.add(pair[0])

        to_be_deleted = set()
        for pair in yl:
            if self.__contains(pair, self_loop):
                to_be_deleted.add(pair)
        for pair in to_be_deleted:
            yl.discard(pair)
        return yl

    def __issubset(self, a, b):
        if set(a[0]).issubset(b[0]) and set(a[1]).issubset(b[1]):
            return True
        return False

    def __contains(self, a, b):
        # return True if nested tuple "a" contains any letter in set "b"
        # e.g. __contains((('a',), ('b',)), ('b', 'c')) -> True
        return any(j == i[0] for i in a for j in b)

    def get_footprint(self):
        footprint = []
        footprint.append("All transitions: {}".format(self.tl))
        footprint.append("Direct succession: {}".format(self.ds))
        footprint.append("Causality: {}".format(self.cs))
        footprint.append("Parallel: {}".format(self.pr))
        footprint.append("Choice: {}".format(self.ind))
        return '\n'.join(footprint)

    def generate_footprint(self, txtfile='footprint.txt'):
        with open(txtfile, 'w') as f:
            f.write(self.get_footprint())

    def direct_succession(self):
        # x > y
        ds = set()
        for trace in self.log:
            for x, y in zip(trace, trace[1:]):
                ds.add((x, y))
        return ds

    def causality(self):
        # x -> y
        cs = {}
        for pair in self.ds:
            if pair[::-1] not in self.ds:
                if pair[0] in cs.keys():
                    cs[pair[0]].append(pair[1])
                else:
                    cs[pair[0]] = [pair[1]]
        return cs

    def inv_causality(self):
        # only for causality cases which has one succesor
        inv_cs = {}
        for key, values in self.cs.items():
            if len(values) == 1:
                if values[0] in inv_cs.keys():
                    inv_cs[values[0]].append(key)
                else:
                    inv_cs[values[0]] = [key]
        return inv_cs

    def parallel(self):
        # (x || y) & (y || x)
        pr = set()
        for pair in self.ds:
            if pair[::-1] in self.ds:
                pr.add(pair)
        return pr

    def choice(self):
        # (x # y) & (y # x)
        ind = set()  # ind is the abbreviation of independent
        all_permutations = itertools.permutations(self.tl, 2)
        '''for pair in all_permutations:
            if pair not in self.cs and pair[::-1] not in self.cs and pair not in self.pr:
                ind.add(pair)'''
        for pair in all_permutations:
            if pair not in self.ds and pair[::-1] not in self.ds:
                ind.add(pair)
        return ind

    def set_contain(self, s, value):
        for i in s:
            for j in i:
                if j == value:
                    return True

        return False

    def create_graph(self, filename='graph', view=False, l1l=None):
        # adding split gateways based on causality
        for event in self.cs:
            if len(self.cs[event]) > 1:
                if tuple(self.cs[event]) in self.pr:
                    self.G.add_and_split_gateway(event, self.cs[event])
                #elif tuple(self.cs[event]) in self.ind:
                #    self.G.add_xor_split_gateway(event,self.cs[event])
                else:
                    if l1l is not None and event in l1l:
                        temp_cs = self.cs[event]
                        temp_cs.append(event)
                        self.G.add_xor_split_gateway(event, temp_cs)
                    else:
                        self.G.add_xor_split_gateway(event, self.cs[event])

        # adding merge gateways based on inverted causality
        for event in self.inv_cs:
            if len(self.inv_cs[event]) > 1:
                if tuple(self.inv_cs[event]) in self.pr:
                    self.G.add_and_merge_gateway(self.inv_cs[event], event)
                else:
                    if l1l is not None and any(elem in self.inv_cs[event]
                                               for elem in l1l):
                        temp_event = [event]
                        for i in self.inv_cs[event]:
                            temp_event.append(i)
                        self.G.add_xor_merge_split_gateway(
                            self.inv_cs[event], temp_event)
                    else:
                        self.G.add_xor_merge_gateway(self.inv_cs[event], event)
            elif len(self.inv_cs[event]) == 1:
                if l1l is not None and self.inv_cs[event][0] in l1l:
                    temp_inv_cs = [event]
                    temp_inv_cs.append(self.inv_cs[event][0])
                    self.G.add_xor_split_gateway(self.inv_cs[event][0],
                                                 temp_inv_cs)
                else:
                    source = list(self.inv_cs[event])[0]
                    self.G.edge(source, event)

        # adding start event
        self.G.add_event("start")
        if len(self.ti) > 1:
            if tuple(self.ti) in self.pr:
                self.G.add_and_split_gateway("start", self.ti)
            else:
                self.G.add_xor_split_gateway("start", self.ti)
        else:
            self.G.edge("start", list(self.ti)[0])

        # adding end event
        self.G.add_event("end")
        if len(self.to) > 1:
            if tuple(self.to) in self.pr:
                self.G.add_and_merge_gateway(self.to, "end")
            else:
                self.G.add_xor_merge_gateway(self.to, "end")
        else:
            self.G.edge(list(self.to)[0], "end")

        self.G.render('../graphs/' + filename, view=view)

        return self.G