practical.tex 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. \chapter{Practical information}
  2. This chapter describes how to execute and use our proof of concept implementation of the Modelverse.
  3. This implementation follows the previously defined interface, and is implemented in Python.
  4. Other implementations are possible, since each part of the service runs separately and they communicate through the use of sockets.
  5. As such, more efficient implementations in compiled programming languages (\textit{e.g.}, C++) are possible.
  6. \section{Requirements}
  7. The proof of concept implementation uses Python 2.7.
  8. As all aspects are explicitly modelled, this platform is the only dependency.
  9. For the testing framework, \texttt{py.test} is recommended, though it is compatible with the default \texttt{unittest} module of Python.
  10. All mentioned scripts are developed primarily for Linux, using shell scripts.
  11. Often though, Windows batch scripts are provided which should have identical behaviour.
  12. \section{Test suite}
  13. To run the tests, it suffices to execute \texttt{py.test} in the folder of the project.
  14. Since the Modelverse project consists of several subprojects (Modelverse State, Modelverse Kernel, and Modelverse Interface), it should be invoked in each folder seperately.
  15. For this, a script \texttt{run\_tests.sh} is provided.
  16. Additionally, some ``integration'' tests are provided, which set up a complete Modelverse process and accesses it through the usual Modelverse Interface API.
  17. These tests are also ran using the \texttt{run\_tests.sh} script.
  18. \section{Running the Modelverse}
  19. Manually running the Modelverse happens, again, through the invocation of the script \texttt{run\_local\_modelverse.sh}.
  20. This script takes a single parameter: a file containing the initial state of the Modelverse, called \texttt{bootstrap.m}.
  21. Note that this section uses the \texttt{run\_local\_modelverse.sh} script, instead of \texttt{run\_modelverse.sh}.
  22. The former contains an optimized implementation of the Modelverse, which directly couples the Modelverse Kernel and Modelverse State, instead of having them communicate through sockets.
  23. Both situations will work, though the former is much more efficient at this time.
  24. No modifications to either component is necessary for this, as it only changes a small part of the network communication between them (directly coupling both components).
  25. This script will first compile the necessary Modelverse wrapper statechart, and afterwards executes it.
  26. Now that the Modelverse is running, by default on port 8001, it can be accessed through XML/HTTP requests.
  27. \section{Bootstrap file}
  28. The bootstrap file contains the initial state of the Modelverse upon startup.
  29. It contains essential constructs, such as the primitives (\textit{e.g.}, \texttt{integer\_addition}, \texttt{create\_node}), and the initial user (\textit{user\_manager}, for generating further users).
  30. While it should normally not be changed, this initial content can be automatically generated through the \texttt{bootstrap/bootstrap.py} script.
  31. The script contains a basic configuration for determining which primitives need to be loaded, and what the initial structure of the Modelverse should be upon creation.
  32. By default, the bootstrap file initializes each user with code to deserialize an encoded string to a graph that will be merged in the Modelverse State.
  33. After merging, the provided graph will be executed.
  34. If the provided code returns True, a deserialize call will be invoked again, otherwise the user stops execution.
  35. \section{XML/HTTP requests}
  36. As the Modelverse listens for XML/HTTP requests, every possible XML/HTTP request-capable client can be used.
  37. In the limit, this can be even a simple command line tool, such as \textit{curl}.
  38. An example \textit{curl} invocation to create a new user called ``test'' is \texttt{curl http://localhost:8001 -d "op=set\_input\&username=user\_manager\&element\_type=V\&value=\"test\""}.
  39. To get output of the user, the \textit{curl} invocation is \texttt{curl http://localhost:8001 -d "op=get\_output\&username=test\&element\_type=V\&value="}.
  40. \section{Compiling with HUTN}
  41. Manually using the XML/HTTP interface is clearly not desirable for end-users.
  42. As such, an MvI is needed to hide this complexity from the users.
  43. An example MvI, in the form of a HUTN compiler, is provided and will be introduced now.
  44. The compiler can be invoked through the script \texttt{./execute\_as.sh}.
  45. It takes two parameters: the name of the user that needs to be created, and a file containing the HUTN to execute.
  46. The script automatically creates the specified user, compiles the provided file, uploads it, and finally executes it.
  47. As mentioned previously, the default bootstrap file waits for an encoded string that contains a graph.
  48. This graph is then executed and will further act as the service that is being executed.
  49. This way, it is actually possible to define every possible interface by explicitly modelling it.
  50. \section{Examples}
  51. Finally, we introduce some simple examples that show how the HUTN compiler can be used and what the results are.
  52. More examples are provided in the test suite.
  53. \subsection{Simple Action Language Services}
  54. First, to show that every kind of service can be modelled explicitly, we define a simple arithmetic service, shown in Listing~\ref{listing:factorial}.
  55. This service will continuously wait for input, and respond with the factorial of this number.
  56. The example essentially consists of three parts:
  57. \begin{enumerate}
  58. \item \textit{Imports}: as everything is explicitly modelled, even the primitive operations need to be explicitly loaded.
  59. This can be done by including the file ``primitives.al''.
  60. More specific imports are also possible, like ``integer.al'', ``float.al'', etc.
  61. \item \textit{Code}
  62. The actual algorithm is stored here, and is written in a minimal action language syntax.
  63. The core of the algorithm is very similar to how the implementation would be in another implementation langauge.
  64. Most notably, there is currently no support for operators, so each part has to be explicitly invoked as a function.
  65. \item \textit{Main loop}
  66. As the code defines its own interface, a main loop will also be required for our example.
  67. This main loop is just a simple inifite while loop, which takes input, passes it to the defined algorithm, and outputs the result.
  68. In more complex situations, this main loop can contain the actual decoding of the incoming message.
  69. \end{enumerate}
  70. \begin{lstlisting}[caption={Example factorial service.},label=listing:factorial]
  71. include "integer.al"
  72. Integer function factorial(n : Integer):
  73. if(integer_lte(n, 1)):
  74. return 1
  75. else:
  76. return integer_multiplication(n, factorial(integer_subtraction(n, 1)))
  77. while(True):
  78. output(factorial(input()))
  79. \end{lstlisting}
  80. To have the Modelverse execute this piece of code for a specific user, the \texttt{execute\_as.sh} script can be invoked as follows:
  81. \texttt{./execute\_as.sh test factorial.al}.
  82. This will initiate compilation of the action language code to a graph representation, which is subsequently uploaded to the Modelverse.
  83. Now, the Modelverse will start to execute the provided graph, and blocks for input.
  84. A user can now provide input to this method, by sending the input to the previously defined user.
  85. This can be done as follows:
  86. \texttt{curl http://localhost:8001 -d "op=set\_input\&username=test\&element\_type=V\&value=5"}.
  87. After which the Modelverse will start to compute this value.
  88. Immediately after, the output can be requested (as it will block anyway) as follows:
  89. \texttt{curl http://localhost:8001 -d "op=get\_output\&username=test\&element\_type=V\&value="}.
  90. This request will eventually return with a response similar to this:
  91. \texttt{id=12345\&value=120}.
  92. Note that the id might be different, though the value should be identical.
  93. \subsection{Model Conformance Checks}
  94. A more complex example is closer to the problem the Modelverse tries to solve: modelling operations.
  95. Special syntax is provided to create models.
  96. After the models are created, they can be used just like any other element of the Modelverse.
  97. As such, there is no fundamental distinction between a user-made model, and a built-in primitive.
  98. The example in Listing~\ref{listing:conformance} shows how three models are constructed: the SimpleClassDiagram metametamodel, the PetriNet metamodel, and finally a PetriNet model.
  99. Together with the models, a simple conformance check algorithm is defined.
  100. This check can subsequently be executed on each of the exported models, to check whether or not they comply to their metamodel.
  101. A model consists of a name, a colon, the name of the type, and the type mapping between parentheses.
  102. The type mapping should be a dictionary (or an empty node), which will be augmented with the typing information.
  103. The type mapping of multiple models can be stored in a single dictionary, though only a single type per model is allowed.
  104. In the modelling language, the first part constitutes the type of the element, which will be looked up in the specified metamodel.
  105. The second part is the identifier, which will be stored in the model for future referencing.
  106. \begin{lstlisting}[caption={Simple modelling hierarchy, stored in \texttt{models.al}.},label=listing:models.al]
  107. include "primitives.al"
  108. Element typing_scd
  109. typing_scd = create_node()
  110. SimpleClassDiagram : SimpleClassDiagram (typing_scd) {
  111. Class Class()
  112. Type Type(Type)
  113. Type String(String)
  114. Attribute_ Attribute_ (Class, Type)
  115. Attribute_ AttributeAttrs (Attribute_, Type)
  116. Attribute_ Attribute (Class, Type)
  117. AttributeAttrs Name (Attribute, String)
  118. Association Association (Class, Class)
  119. Association Inheritance (Class, Class)
  120. Inheritance (Association, Class)
  121. Inheritance (Attribute_, Class)
  122. }
  123. PetriNet : SimpleClassDiagram (typing_scd) {
  124. Class Place()
  125. Attribute Place.tokens = Integer
  126. Name = "tokens"
  127. Class Transition()
  128. Association T2P (Transition, Place)
  129. Attribute T2P.weight = Integer
  130. Name = "weight"
  131. Association P2T (Place, Transition)
  132. Attribute P2T.weight = Integer
  133. Name = "weight"
  134. }
  135. my_net : PetriNet (typing_scd) {
  136. Place p1()
  137. Place.tokens = 3
  138. Place p2()
  139. Place.tokens = 0
  140. Transition t1()
  141. P2T (p1, t1)
  142. P2T.weight = 1
  143. T2P (t1, p2)
  144. T2P.weight = 2
  145. }
  146. export_node("metamodels/simpleclassdiagram", SimpleClassDiagram)
  147. export_node("metamodels/petrinet", PetriNet)
  148. export_node("models/my_net", my_net)
  149. \end{lstlisting}
  150. \begin{lstlisting}[caption={Conformance service, stored in \texttt{conformance.al}.},label=listing:conformance]
  151. include "models.al"
  152. include "conformance_scd.al"
  153. while (True):
  154. output(conforms(input()))
  155. \end{lstlisting}