123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- \chapter{Practical information}
- This chapter describes how to execute and use our proof of concept implementation of the Modelverse.
- This implementation follows the previously defined interface, and is implemented in Python.
- Other implementations are possible, since each part of the service runs separately and they communicate through the use of sockets.
- As such, more efficient implementations in compiled programming languages (\textit{e.g.}, C++) are possible.
- \section{Requirements}
- The proof of concept implementation uses Python 2.7.
- As all aspects are explicitly modelled, this platform is the only dependency.
- For the testing framework, \texttt{py.test} is recommended, though it is compatible with the default \texttt{unittest} module of Python.
- All mentioned scripts are developed primarily for Linux, using shell scripts.
- Often though, Windows batch scripts are provided which should have identical behaviour.
- \section{Test suite}
- To run the tests, it suffices to execute \texttt{py.test} in the folder of the project.
- Since the Modelverse project consists of several subprojects (Modelverse State, Modelverse Kernel, and Modelverse Interface), it should be invoked in each folder seperately.
- For this, a script \texttt{run\_tests.sh} is provided.
- Additionally, some ``integration'' tests are provided, which set up a complete Modelverse process and accesses it through the usual Modelverse Interface API.
- These tests are also ran using the \texttt{run\_tests.sh} script.
- \section{Running the Modelverse}
- Manually running the Modelverse happens, again, through the invocation of the script \texttt{run\_local\_modelverse.sh}.
- This script takes a single parameter: a file containing the initial state of the Modelverse, called \texttt{bootstrap.m}.
- Note that this section uses the \texttt{run\_local\_modelverse.sh} script, instead of \texttt{run\_modelverse.sh}.
- 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.
- Both situations will work, though the former is much more efficient at this time.
- 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).
- This script will first compile the necessary Modelverse wrapper statechart, and afterwards executes it.
- Now that the Modelverse is running, by default on port 8001, it can be accessed through XML/HTTP requests.
- \section{Bootstrap file}
- The bootstrap file contains the initial state of the Modelverse upon startup.
- 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).
- While it should normally not be changed, this initial content can be automatically generated through the \texttt{bootstrap/bootstrap.py} script.
- 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.
- 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.
- After merging, the provided graph will be executed.
- If the provided code returns True, a deserialize call will be invoked again, otherwise the user stops execution.
- \section{XML/HTTP requests}
- As the Modelverse listens for XML/HTTP requests, every possible XML/HTTP request-capable client can be used.
- In the limit, this can be even a simple command line tool, such as \textit{curl}.
- 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\""}.
- 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="}.
- \section{Compiling with HUTN}
- Manually using the XML/HTTP interface is clearly not desirable for end-users.
- As such, an MvI is needed to hide this complexity from the users.
- An example MvI, in the form of a HUTN compiler, is provided and will be introduced now.
- The compiler can be invoked through the script \texttt{./execute\_as.sh}.
- It takes two parameters: the name of the user that needs to be created, and a file containing the HUTN to execute.
- The script automatically creates the specified user, compiles the provided file, uploads it, and finally executes it.
- As mentioned previously, the default bootstrap file waits for an encoded string that contains a graph.
- This graph is then executed and will further act as the service that is being executed.
- This way, it is actually possible to define every possible interface by explicitly modelling it.
- \section{Examples}
- Finally, we introduce some simple examples that show how the HUTN compiler can be used and what the results are.
- More examples are provided in the test suite.
- \subsection{Simple Action Language Services}
- First, to show that every kind of service can be modelled explicitly, we define a simple arithmetic service, shown in Listing~\ref{listing:factorial}.
- This service will continuously wait for input, and respond with the factorial of this number.
- The example essentially consists of three parts:
- \begin{enumerate}
- \item \textit{Imports}: as everything is explicitly modelled, even the primitive operations need to be explicitly loaded.
- This can be done by including the file ``primitives.al''.
- More specific imports are also possible, like ``integer.al'', ``float.al'', etc.
- \item \textit{Code}
- The actual algorithm is stored here, and is written in a minimal action language syntax.
- The core of the algorithm is very similar to how the implementation would be in another implementation langauge.
- Most notably, there is currently no support for operators, so each part has to be explicitly invoked as a function.
- \item \textit{Main loop}
- As the code defines its own interface, a main loop will also be required for our example.
- This main loop is just a simple inifite while loop, which takes input, passes it to the defined algorithm, and outputs the result.
- In more complex situations, this main loop can contain the actual decoding of the incoming message.
- \end{enumerate}
- \begin{lstlisting}[caption={Example factorial service.},label=listing:factorial]
- include "integer.al"
- Integer function factorial(n : Integer):
- if(integer_lte(n, 1)):
- return 1
- else:
- return integer_multiplication(n, factorial(integer_subtraction(n, 1)))
- while(True):
- output(factorial(input()))
- \end{lstlisting}
- To have the Modelverse execute this piece of code for a specific user, the \texttt{execute\_as.sh} script can be invoked as follows:
- \texttt{./execute\_as.sh test factorial.al}.
- This will initiate compilation of the action language code to a graph representation, which is subsequently uploaded to the Modelverse.
- Now, the Modelverse will start to execute the provided graph, and blocks for input.
- A user can now provide input to this method, by sending the input to the previously defined user.
- This can be done as follows:
- \texttt{curl http://localhost:8001 -d "op=set\_input\&username=test\&element\_type=V\&value=5"}.
- After which the Modelverse will start to compute this value.
- Immediately after, the output can be requested (as it will block anyway) as follows:
- \texttt{curl http://localhost:8001 -d "op=get\_output\&username=test\&element\_type=V\&value="}.
- This request will eventually return with a response similar to this:
- \texttt{id=12345\&value=120}.
- Note that the id might be different, though the value should be identical.
- \subsection{Model Conformance Checks}
- A more complex example is closer to the problem the Modelverse tries to solve: modelling operations.
- Special syntax is provided to create models.
- After the models are created, they can be used just like any other element of the Modelverse.
- As such, there is no fundamental distinction between a user-made model, and a built-in primitive.
- The example in Listing~\ref{listing:conformance} shows how three models are constructed: the SimpleClassDiagram metametamodel, the PetriNet metamodel, and finally a PetriNet model.
- Together with the models, a simple conformance check algorithm is defined.
- This check can subsequently be executed on each of the exported models, to check whether or not they comply to their metamodel.
- A model consists of a name, a colon, the name of the type, and the type mapping between parentheses.
- The type mapping should be a dictionary (or an empty node), which will be augmented with the typing information.
- The type mapping of multiple models can be stored in a single dictionary, though only a single type per model is allowed.
- In the modelling language, the first part constitutes the type of the element, which will be looked up in the specified metamodel.
- The second part is the identifier, which will be stored in the model for future referencing.
- \begin{lstlisting}[caption={Simple modelling hierarchy, stored in \texttt{models.al}.},label=listing:models.al]
- include "primitives.al"
- Element typing_scd
- typing_scd = create_node()
- SimpleClassDiagram : SimpleClassDiagram (typing_scd) {
- Class Class()
- Type Type(Type)
- Type String(String)
- Attribute_ Attribute_ (Class, Type)
- Attribute_ AttributeAttrs (Attribute_, Type)
- Attribute_ Attribute (Class, Type)
- AttributeAttrs Name (Attribute, String)
- Association Association (Class, Class)
- Association Inheritance (Class, Class)
- Inheritance (Association, Class)
- Inheritance (Attribute_, Class)
- }
- PetriNet : SimpleClassDiagram (typing_scd) {
- Class Place()
- Attribute Place.tokens = Integer
- Name = "tokens"
- Class Transition()
- Association T2P (Transition, Place)
- Attribute T2P.weight = Integer
- Name = "weight"
- Association P2T (Place, Transition)
- Attribute P2T.weight = Integer
- Name = "weight"
- }
- my_net : PetriNet (typing_scd) {
- Place p1()
- Place.tokens = 3
- Place p2()
- Place.tokens = 0
- Transition t1()
- P2T (p1, t1)
- P2T.weight = 1
- T2P (t1, p2)
- T2P.weight = 2
- }
- export_node("metamodels/simpleclassdiagram", SimpleClassDiagram)
- export_node("metamodels/petrinet", PetriNet)
- export_node("models/my_net", my_net)
- \end{lstlisting}
- \begin{lstlisting}[caption={Conformance service, stored in \texttt{conformance.al}.},label=listing:conformance]
- include "models.al"
- include "conformance_scd.al"
- while (True):
- output(conforms(input()))
- \end{lstlisting}
|