12.6. EpiM

12.6.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.

Explore in the playground.

 1 from mod.epim.process import Process, names
 2 
 3 # MØD print options
 4 printer = GraphPrinter()
 5 
 6 # Specify the names to be used:
 7 x, y, z, w = names("x y z w")
 8 
 9 # Specify the behavior of a process
10 p1 = Process().input(x, z).output(z, w)
11 p2 = Process().output(x, y)
12 P = p1 | p2
13 
14 # Encode the process as a MØD graph:
15 G = P.encode()
16 
17 # Put a visualisation of the encoding in the summary:
18 G.print(printer)

12.6.2. A Process Encoding with Restrictions

We can restrict names of a process.

Explore in the playground.

 1 from mod.epim.process import Process, names
 2 
 3 # MØD print options
 4 printer = GraphPrinter()
 5 
 6 # Specify the names to be used:
 7 x, y, z, w = names("x y z w")
 8 
 9 # Specify the behavior of a process
10 p1 = Process().input(x, z).output(z, w)
11 p2 = Process().restrict(x).output(x, y)
12 P = p1 | p2
13 
14 # Encode the process as a MØD graph:
15 G = P.encode()
16 
17 # Put a visualisation of the encoding in the summary:
18 G.print(printer)

12.6.3. A Recursive Encoding

We can also specify process calls in an encoding.

Explore in the playground.

 1 from mod.epim.process import Process, names
 2 
 3 # MØD print options
 4 printer = GraphPrinter()
 5 
 6 # Specify the names to be used:
 7 x, 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".
12 A = Process().input(x, y).call("A", [x])
13 
14 # Encode A and put a visualisation of the encoding in the summary:
15 A.encode().print(printer)

12.6.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.

Explore in the playground.

 1 from mod.epim.gen_image import image_config
 2 from mod.epim.process import Process, names
 3 
 4 # Show the names of a process encoding: 
 5 image_config.show_variables = True
 6 
 7 # Show the pointer vertices used for encoding process calls:
 8 image_config.show_pointers = True
 9 
10 # Show the special root vertex "go" of an encoding:
11 image_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:
15 image_config.collapse_two_edges = False
16 
17 # MØD print options
18 printer = GraphPrinter()
19 
20 # Specify the names to be used:
21 x, y, z, w = names("x y z w")
22 
23 # Specify the behavior of a process:
24 p1 = Process().input(x, z).output(z, w)
25 p2 = Process().output(x, y)
26 P = p1 | p2
27 
28 # Encode and print P
29 G = P.encode()
30 G.print(printer)

12.6.5. Compute Execution Spaces

We can compute the execution space of a process.

Explore in the playground.

 1 from mod.epim.transform.reduction_dg import ReductionDG
 2 from mod.epim.process import Process, names
 3 
 4 # Specify the names to be used:
 5 x, y, z, w = names("x y z w")
 6 
 7 # Specify the behavior of a process:
 8 p1 = Process().input(x, z).output(z, w)
 9 p2 = Process().output(x, y) + Process().output(x, y)
10 P = (p1 | p2)
11 
12 # Compute the execution space for P
13 exec_space = ReductionDG(P)
14 exec_space.calc()
15 
16 # Print the resulting derivation graph to the summary PDF:
17 exec_space.print()
18 # exec_space.print(True) #prints the entire derivation graph

12.6.6. Process Execution Spaces with Recursive Processes

We can compute the execution space of processes defined with recursive processes.

Explore in the playground.

 1 from mod.epim.transform.reduction_dg import ReductionDG
 2 from mod.epim.process import Process, names
 3 from mod.epim.recursive_process import RecursiveProcess
 4 
 5 # Specify the names to be used:
 6 x, y, z = names("x y z")
 7 
 8 # Define a recursive process:
 9 rp = RecursiveProcess()
10 
11 # Specify the name, arguments, and behavior of a recursive process:
12 A = Process().input(x, y).call("A", [y])
13 rp.add("A", [x], A)
14 
15 B = Process().output(x, x).call("B", [x])
16 rp.add("B", [x], B)
17 
18 # Specify the behavior of a process:
19 P = A | B
20 
21 # Compute the execution space for P provided with the recursive process rp:
22 exec_space = ReductionDG(P, rp)
23 exec_space.calc()
24 
25 # Print the resulting derivation graph to the summary PDF:
26 exec_space.print()

12.6.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.

Explore in the playground.

 1 from mod.epim.process import Process, names, Name, process_config
 2 from mod.epim.transform.reduction_dg import ReductionDG
 3 from mod.epim.recursive_process import RecursiveProcess
 4 
 5 # Do not print the arguments of an encoded process call:
 6 process_config.print_args = False
 7 
 8 # Specify the names to be used:
 9 s, n, pn, j, h, cu, ki, d, x = names("s n pn j h cu ki d x")
10 free_names = [s, n, ki, cu]
11 
12 # Define a recursive process:
13 rp = RecursiveProcess()
14 
15 # Specify the name, arguments, and behavior of a recursive process:
16 P = Process().output(s, n).input(n, d).call("Pp", free_names)
17 rp.add("P", free_names, P)
18 
19 Pp = Process().input(ki, x) + Process().input(cu, x).call("P", free_names)
20 rp.add("Pp", free_names, Pp)
21 
22 J = Process().input(s, pn).output(pn, j).output(cu, j).call("J", free_names)
23 rp.add("J", free_names, J)
24 
25 H = Process().input(s, pn).output(pn, h).output(ki, h).call("H", free_names)
26 rp.add("H", free_names, H)
27 
28 # Define the process Hospital:
29 Hospital = P | J | H
30 
31 # Compute the execution space of Hospital given the recursive process rp:
32 exec_space = ReductionDG(Hospital, rp)
33 exec_space.calc()
34 
35 # Print the resulting derivation graph to the summary PDF:
36 exec_space.print()