def apply(tree, parameters=None):
    '''
    Only supports loops with 2 children!
    :param tree:
    :return:
    '''
    net = petrinet.PetriNet(name=str(tree))
    if len(tree.children) == 0:
        pn_util.add_transition(net, label=tree.label)
    else:
        sub_nets = list()
        for c in tree.children:
            sub_net, ini, fin = apply(c)
            sub_nets.append(sub_net)
        pn_util.merge(net, sub_nets)
        switch = {
            pt_opt.SEQUENCE: construct_sequence_pattern,
            pt_opt.XOR: construct_xor_pattern,
            pt_opt.PARALLEL: construct_and_pattern,
            pt_opt.LOOP: construct_loop_pattern
        }
        net, ini, fin = switch[tree.operator](net, sub_nets)
    if tree.parent is None:
        p_ini = pn_util.add_place(net)
        p_fin = pn_util.add_place(net)
        pn_util.add_arc_from_to(p_ini, _get_src_transition(net), net)
        pn_util.add_arc_from_to(_get_sink_transition(net), p_fin, net)
        return net, petrinet.Marking({p_ini: 1}), petrinet.Marking({p_fin: 1})
    return net, petrinet.Marking(), petrinet.Marking()
def construct_loop_pattern(net, sub_nets):
    assert (len(sub_nets) == 2)
    p_s = pn_util.add_place(net)
    p_t = pn_util.add_place(net)
    pn_util.add_arc_from_to(p_s, _get_src_transition(sub_nets[0]), net)
    pn_util.add_arc_from_to(p_t, _get_src_transition(sub_nets[1]), net)
    pn_util.add_arc_from_to(_get_sink_transition(sub_nets[0]), p_t, net)
    pn_util.add_arc_from_to(_get_sink_transition(sub_nets[1]), p_s, net)
    net, ini, fin = _add_src_sink_transitions(net, p_s, p_t)
    return net, petrinet.Marking(), petrinet.Marking()
def construct_sequence_pattern(net, sub_nets):
    places = [None] * (len(sub_nets) + 1)
    for i in range(len(sub_nets) + 1):
        places[i] = pn_util.add_place(net)
    for i in range(len(sub_nets)):
        pn_util.add_arc_from_to(places[i], _get_src_transition(sub_nets[i]),
                                net)
        pn_util.add_arc_from_to(_get_sink_transition(sub_nets[i]),
                                places[i + 1], net)
    src = pn_util.add_transition(net)
    pn_util.add_arc_from_to(src, places[0], net)
    sink = pn_util.add_transition(net)
    pn_util.add_arc_from_to(places[len(places) - 1], sink, net)
    return net, petrinet.Marking(), petrinet.Marking()
def construct_and_pattern(net, sub_nets):
    p_s = [None] * len(sub_nets)
    p_t = [None] * len(sub_nets)
    for i in range(len(sub_nets)):
        p_s[i] = pn_util.add_place(net)
        p_t[i] = pn_util.add_place(net)
        pn_util.add_arc_from_to(p_s[i], _get_src_transition(sub_nets[i]), net)
        pn_util.add_arc_from_to(_get_sink_transition(sub_nets[i]), p_t[i], net)
    src = pn_util.add_transition(net)
    for p in p_s:
        pn_util.add_arc_from_to(src, p, net)
    sink = pn_util.add_transition(net)
    for p in p_t:
        pn_util.add_arc_from_to(p, sink, net)
    return net, petrinet.Marking(), petrinet.Marking()
Ejemplo n.º 5
0
def check_easy_soundness_of_wfnet(net):
    """
    Checks the easy soundness of a workflow net

    Parameters
    -------------
    net
        Petri net

    Returns
    -------------
    boolean
        Boolean value
    """
    source = list(x for x in net.places if len(x.in_arcs) == 0)[0]
    sink = list(x for x in net.places if len(x.out_arcs) == 0)[0]

    ini = petrinet.Marking({source: 1})
    fin = petrinet.Marking({sink: 1})

    return check_easy_soundness_net_in_fin_marking(net, ini, fin)
Ejemplo n.º 6
0
def default_staterep_to_marking(staterep, place_map):
    place_groups = re.split(r'([a-zA-Z0-9]+_[0-9]+)', staterep)
    places = []
    # print('Splitted groups: {}'.format(place_groups))
    for grp in place_groups:
        if grp == '' or grp == '_':
            continue
        place_name, nb_tokens = grp.split('_')
        # print('Group: {}, place name: {}, no. of tokens: {}'.format(grp, place_name, nb_tokens))
        place = place_map[place_name]
        places.extend([place for _ in range(int(nb_tokens))])
    marking = petri.Marking(places)
    return marking
def _add_src_sink_transitions(net, p_s, p_t):
    src = pn_util.add_transition(net)
    pn_util.add_arc_from_to(src, p_s, net)
    sink = pn_util.add_transition(net)
    pn_util.add_arc_from_to(p_t, sink, net)
    return net, petrinet.Marking(), petrinet.Marking()
Ejemplo n.º 8
0
    arcs = [
        p0_a, p1_c, p2_inv0, p3_e, p4_f, p5_g, p6_inv1, p7_inv1, p8_inv1, p9_d,
        p10_h, p10_b, a_p1, c_p2, inv0_p3, inv0_p4, inv0_p5, e_p6, f_p7, g_p8,
        inv1_p9, d_p10, h_p1, b_p11
    ]

    for arc in arcs:
        arc.source.out_arcs.add(arc)
        arc.target.in_arcs.add(arc)

    net.transitions.update(trans)
    net.places.update(places)
    net.arcs.update(arcs)

    init_marking = petri.Marking([p0])
    final_marking = petri.Marking([p11])

    out_fp = './net.dot'
    gviz = vis_factory.apply(net, init_marking, final_marking)
    gviz.save(out_fp)

    # out_fp = './test-net.pnml'
    # exporter.pnml.export_net(net, init_marking, out_fp, final_marking=final_marking)

    # build the reachability graph
    is_inv = lambda t: t.label is None
    rg, inv_states = build_reachability_graph(net, init_marking, is_inv)

    collapse_inv_trans(rg, inv_states)
Ejemplo n.º 9
0
def build_net1():
    net = petri.PetriNet(name='net1')

    # transitions
    a = petri.PetriNet.Transition('a', label='a')
    b = petri.PetriNet.Transition('b', label='b')
    c = petri.PetriNet.Transition('c', label='c')
    d = petri.PetriNet.Transition('d', label='d')
    e = petri.PetriNet.Transition('e', label='e')
    f = petri.PetriNet.Transition('f', label='f')
    g = petri.PetriNet.Transition('g', label='g')

    trans = [a, b, c, d, e, f, g]

    # places
    p1 = petri.PetriNet.Place('p1')
    p2 = petri.PetriNet.Place('p2')
    p3 = petri.PetriNet.Place('p3')
    p4 = petri.PetriNet.Place('p4')
    p5 = petri.PetriNet.Place('p5')
    p6 = petri.PetriNet.Place('p6')
    p7 = petri.PetriNet.Place('p7')

    places = [p1, p2, p3, p4, p5, p6, p7]

    # arcs
    p1_a = petri.PetriNet.Arc(p1, a)
    p2_b = petri.PetriNet.Arc(p2, b)
    p2_c = petri.PetriNet.Arc(p2, c)
    p3_d = petri.PetriNet.Arc(p3, d)
    p4_e = petri.PetriNet.Arc(p4, e)
    p5_e = petri.PetriNet.Arc(p5, e)
    p6_f = petri.PetriNet.Arc(p6, f)
    p6_g = petri.PetriNet.Arc(p6, g)

    a_p2 = petri.PetriNet.Arc(a, p2)
    a_p3 = petri.PetriNet.Arc(a, p3)
    b_p4 = petri.PetriNet.Arc(b, p4)
    c_p4 = petri.PetriNet.Arc(c, p4)
    d_p5 = petri.PetriNet.Arc(d, p5)
    e_p6 = petri.PetriNet.Arc(e, p6)
    f_p2 = petri.PetriNet.Arc(f, p2)
    f_p3 = petri.PetriNet.Arc(f, p3)
    g_p7 = petri.PetriNet.Arc(g, p7)

    arcs = [
        p1_a, p2_b, p2_c, p3_d, p4_e, p5_e, p6_f, p6_g,
        a_p2, a_p3, b_p4, c_p4, d_p5, e_p6, f_p2, f_p3, g_p7
    ]

    for arc in arcs:
        arc.source.out_arcs.add(arc)
        arc.target.in_arcs.add(arc)

    net.transitions.update(trans)
    net.places.update(places)
    net.arcs.update(arcs)

    init_marking = petri.Marking([p1])
    final_marking = petri.Marking([p7])

    return net, init_marking, final_marking
def check_loops_generating_tokens(net0):
    """
    Check if the Petri net contains loops generating tokens

    Parameters
    ------------
    net0
        Petri net

    Returns
    ------------
    boolean
        Boolean value (True if the net has loops generating tokens)
    """
    net = deepcopy(net0)
    petri_utils.decorate_transitions_prepostset(net)
    graph, inv_dictionary = petri_utils.create_networkx_directed_graph(net)
    dictionary = {y:x for x,y in inv_dictionary.items()}
    loops_trans = petri_utils.get_cycles_petri_net_transitions(net)
    for loop in loops_trans:
        m = petrinet.Marking()
        for index, trans in enumerate(loop):
            m = m + trans.add_marking

        visited_couples = set()
        while True:
            changed_something = False
            # if there are no places with positive marking replaying the loop, then we are fine
            neg_places = [p for p in m if m[p] < 0]
            pos_places = [p for p in m if m[p] > 0]
            for p1 in pos_places:
                # if there are no places with negative marking replaying the loop, then we are doomed
                for p2 in neg_places:
                    if not ((p1, p2)) in visited_couples:
                        visited_couples.add((p1, p2))
                        # otherwise, do a check if there is a path in the workflow net between the two places

                        # this exploration is based on heuristics; indeed, since we can enter the cycle multiple times
                        # it does not really matter if we reach suddenly the optimal path
                        #
                        # another option is to use the exploration provided in explore_path (that is based on alignments)
                        spath = None
                        try:
                            spath = nx.algorithms.shortest_paths.generic.shortest_path(graph, dictionary[p1], dictionary[p2])
                        except:
                            pass
                        if spath is not None:
                            trans = [inv_dictionary[x] for x in spath if type(inv_dictionary[x]) is petrinet.PetriNet.Transition]
                            sec_m0 = petrinet.Marking()
                            for t in trans:
                                sec_m0 = sec_m0 + t.add_marking
                            sec_m = petrinet.Marking()
                            for place in m:
                                if place in sec_m0:
                                    sec_m[place] = sec_m0[place]
                            m1 = m + sec_m
                            # the exploration is (in part) successful
                            if m1[p1] == 0:
                                m = m1
                                changed_something = True
                                break
                if not changed_something:
                    break
            if not changed_something:
                break

        # at this point, we have definitely created one token
        if sum(m[place] for place in m) > 0:
            return True

    return False