10.5. EpiM¶
10.5.1. A Basic Process Encoding¶
These examples shows the basic usage of EpiM. After each run a PDF summary is compiled. We let in(x) and out(x) denote the input and output operators of a process respectively.
1from mod.epim.process import Process, names
2
3# MØD print options
4printer = GraphPrinter()
5
6# Specify the names to be used:
7x, y, z, w = names("x y z w")
8
9# Specify the behavior of a process
10p1 = Process().input(x, z).output(z, w)
11p2 = Process().output(x, y)
12P = p1 | p2
13
14# Encode the process as a MØD graph:
15G = P.encode()
16
17# Put a visualisation of the encoding in the summary:
18G.print(printer)
10.5.2. A Process Encoding with Restrictions¶
We can restrict names of a process.
1from mod.epim.process import Process, names
2
3# MØD print options
4printer = GraphPrinter()
5
6# Specify the names to be used:
7x, y, z, w = names("x y z w")
8
9# Specify the behavior of a process
10p1 = Process().input(x, z).output(z, w)
11p2 = Process().restrict(x).output(x, y)
12P = p1 | p2
13
14# Encode the process as a MØD graph:
15G = P.encode()
16
17# Put a visualisation of the encoding in the summary:
18G.print(printer)
10.5.3. A Recursive Encoding¶
We can also specify process calls in an encoding.
1from mod.epim.process import Process, names
2
3# MØD print options
4printer = GraphPrinter()
5
6# Specify the names to be used:
7x, y = names("x y")
8
9# Specify the behavior of a process
10# Note, the second argument to call() is
11# the arguments passed to the recursive invocation of "A".
12A = Process().input(x, y).call("A", [x])
13
14# Encode A and put a visualisation of the encoding in the summary:
15A.encode().print(printer)
10.5.4. Config for Visualization of Encodings¶
The graphs of the encoded processes can be filtered and “prettified” using either the print options used by MØD for graph visualization or the image config provided by EpiM.
1from mod.epim.gen_image import image_config
2from mod.epim.process import Process, names
3
4# Show the names of a process encoding:
5image_config.show_variables = True
6
7# Show the pointer vertices used for encoding process calls:
8image_config.show_pointers = True
9
10# Show the special root vertex "go" of an encoding:
11image_config.show_root = True
12
13# Hide implementation detail specific vertices such as
14# the vertices with terms t(p) or t(s) with degrees of 2:
15image_config.collapse_two_edges = False
16
17# MØD print options
18printer = GraphPrinter()
19
20# Specify the names to be used:
21x, y, z, w = names("x y z w")
22
23# Specify the behavior of a process:
24p1 = Process().input(x, z).output(z, w)
25p2 = Process().output(x, y)
26P = p1 | p2
27
28# Encode and print P
29G = P.encode()
30G.print(printer)
10.5.5. Compute Execution Spaces¶
We can compute the execution space of a process.
1from mod.epim.transform.reduction_dg import ReductionDG
2from mod.epim.process import Process, names
3
4# Specify the names to be used:
5x, y, z, w = names("x y z w")
6
7# Specify the behavior of a process:
8p1 = Process().input(x, z).output(z, w)
9p2 = Process().output(x, y) + Process().output(x, y)
10P = (p1 | p2)
11
12# Compute the execution space for P
13exec_space = ReductionDG(P)
14exec_space.calc()
15
16# Print the resulting derivation graph to the summary PDF:
17exec_space.print()
18# exec_space.print(True) #prints the entire derivation graph
10.5.6. Process Execution Spaces with Recursive Processes¶
We can compute the execution space of processes defined with recursive processes.
1from mod.epim.transform.reduction_dg import ReductionDG
2from mod.epim.process import Process, names
3from mod.epim.recursive_process import RecursiveProcess
4
5# Specify the names to be used:
6x, y, z = names("x y z")
7
8# Define a recursive process:
9rp = RecursiveProcess()
10
11# Specify the name, arguments, and behavior of a recursive process:
12A = Process().input(x, y).call("A", [y])
13rp.add("A", [x], A)
14
15B = Process().output(x, x).call("B", [x])
16rp.add("B", [x], B)
17
18# Specify the behavior of a process:
19P = A | B
20
21# Compute the execution space for P provided with the recursive process rp:
22exec_space = ReductionDG(P, rp)
23exec_space.calc()
24
25# Print the resulting derivation graph to the summary PDF:
26exec_space.print()
10.5.7. Hospital¶
The execution space for the process Hospital. From the execution space, we see that Hospital can end up in a deadlock. This happens specifically, when the process P synchronizes with the process H.
1from mod.epim.process import Process, names, Name, process_config
2from mod.epim.transform.reduction_dg import ReductionDG
3from mod.epim.recursive_process import RecursiveProcess
4
5# Do not print the arguments of an encoded process call:
6process_config.print_args = False
7
8# Specify the names to be used:
9s, n, pn, j, h, cu, ki, d, x = names("s n pn j h cu ki d x")
10free_names = [s, n, ki, cu]
11
12# Define a recursive process:
13rp = RecursiveProcess()
14
15# Specify the name, arguments, and behavior of a recursive process:
16P = Process().output(s, n).input(n, d).call("Pp", free_names)
17rp.add("P", free_names, P)
18
19Pp = Process().input(ki, x) + Process().input(cu, x).call("P", free_names)
20rp.add("Pp", free_names, Pp)
21
22J = Process().input(s, pn).output(pn, j).output(cu, j).call("J", free_names)
23rp.add("J", free_names, J)
24
25H = Process().input(s, pn).output(pn, h).output(ki, h).call("H", free_names)
26rp.add("H", free_names, H)
27
28# Define the process Hospital:
29Hospital = P | J | H
30
31# Compute the execution space of Hospital given the recursive process rp:
32exec_space = ReductionDG(Hospital, rp)
33exec_space.calc()
34
35# Print the resulting derivation graph to the summary PDF:
36exec_space.print()