|
@@ -172,8 +172,8 @@
|
|
|
" ('State.name', 'String'),\n",
|
|
|
" ('Transition', 'Association'),\n",
|
|
|
" ('Transition.name', 'String'),\n",
|
|
|
- " ('__1049623', 'Class_name'),\n",
|
|
|
- " ('__1049695', 'Class_name')}"
|
|
|
+ " ('__1049544', 'Class_name'),\n",
|
|
|
+ " ('__1049616', 'Class_name')}"
|
|
|
]
|
|
|
},
|
|
|
"execution_count": 7,
|
|
@@ -193,7 +193,7 @@
|
|
|
{
|
|
|
"data": {
|
|
|
"text/plain": [
|
|
|
- "'__1054163'"
|
|
|
+ "'__1054084'"
|
|
|
]
|
|
|
},
|
|
|
"execution_count": 8,
|
|
@@ -257,8 +257,8 @@
|
|
|
"name": "stdout",
|
|
|
"output_type": "stream",
|
|
|
"text": [
|
|
|
- "All initial element IDs: {'__1063142'}\n",
|
|
|
- "All state element IDs: {'__1054163', '__1063142'}\n"
|
|
|
+ "All initial element IDs: {'__1063063'}\n",
|
|
|
+ "All state element IDs: {'__1063063', '__1054084'}\n"
|
|
|
]
|
|
|
}
|
|
|
],
|
|
@@ -362,7 +362,7 @@
|
|
|
"name": "stdout",
|
|
|
"output_type": "stream",
|
|
|
"text": [
|
|
|
- "Lower cardinality violation for outgoing edge of type State_name at NODE __1054163 (ID: 1054163)\n"
|
|
|
+ "Lower cardinality violation for outgoing edge of type State_name at NODE __1054084 (ID: 1054084)\n"
|
|
|
]
|
|
|
}
|
|
|
],
|
|
@@ -755,6 +755,347 @@
|
|
|
"define_attribute(mm, transition, \"script\", al_attr)\n",
|
|
|
"attribute_optional(mm, transition, \"script\", True)"
|
|
|
]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Semantics"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "While we have created the syntax of the new language, it should still be possible to define the semantics.\n",
|
|
|
+ "The Modelverse supports three main types of activity, each with their own ideal problem domain."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "## Manual"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "The first type of activity is also the easiest to define, as it is a manual activity.\n",
|
|
|
+ "Many types of activity, or modifications of a model, have to be done manually as they augment information.\n",
|
|
|
+ "For example, refinement is a typical operation that requires a modeller to manually add information to the model.\n",
|
|
|
+ "\n",
|
|
|
+ "For our own defined FSAs, assume that we want to add a *revise* activity, in which the modeller is prompted to modify the model.\n",
|
|
|
+ "While this does not give much information to the Modelverse, it is required, for example, to integrate manual activities in a process model."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 22,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "transformation_add_MANUAL({\"FSA\": \"formalisms/MyOwnFSA\"}, {\"FSA\": \"formalisms/MyOwnFSA\"}, \"formalisms/MyOwnFSA_activities/revise\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Now we can see it in action.\n",
|
|
|
+ "But as was mentioned, it will take manual operations, in our case through the use of a callback function."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 23,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Before:\n",
|
|
|
+ "[]\n",
|
|
|
+ "After:\n",
|
|
|
+ "[{'__id': '__1278360', '__type': 'State', 'name': 'new_state'}]\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "def callback(model):\n",
|
|
|
+ " state = instantiate(model, \"FSA/State\")\n",
|
|
|
+ " attr_assign(model, state, \"name\", \"new_state\")\n",
|
|
|
+ " \n",
|
|
|
+ "model_add(\"models/my_FSA\", \"formalisms/MyOwnFSA\")\n",
|
|
|
+ "\n",
|
|
|
+ "print(\"Before:\")\n",
|
|
|
+ "print(element_list_nice(\"models/my_FSA\"))\n",
|
|
|
+ "\n",
|
|
|
+ "transformation_execute_MANUAL(\"formalisms/MyOwnFSA_activities/revise\", {\"FSA\": \"models/my_FSA\"}, {\"FSA\": \"models/my_FSA\"}, callback)\n",
|
|
|
+ "\n",
|
|
|
+ "print(\"After:\")\n",
|
|
|
+ "print(element_list_nice(\"models/my_FSA\"))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "## Action Language"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Another typical execution scenario is for procedural operations to execute.\n",
|
|
|
+ "In the simplest case, this merely calls some action language code with the selected model as a parameter.\n",
|
|
|
+ "Note that this parameter will be a single model, consisting of the merged model and metamodel.\n",
|
|
|
+ "\n",
|
|
|
+ "For our own defined FSAs, assume that we want to add a simple simulation algorithm.\n",
|
|
|
+ "Note the \"return True\" at the end, signifying that the operation was terminated OK and that changes can be propagated."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 24,
|
|
|
+ "metadata": {
|
|
|
+ "scrolled": false
|
|
|
+ },
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "transformation_add_AL({\"FSA\": \"formalisms/MyOwnFSA\"}, {}, \"formalisms/MyOwnFSA_activities/simulate\", \"\"\"\n",
|
|
|
+ "include \"primitives.alh\"\n",
|
|
|
+ "include \"modelling.alh\"\n",
|
|
|
+ "include \"object_operations.alh\"\n",
|
|
|
+ "include \"conformance_scd.alh\"\n",
|
|
|
+ "include \"io.alh\"\n",
|
|
|
+ "include \"metamodels.alh\"\n",
|
|
|
+ "include \"mini_modify.alh\"\n",
|
|
|
+ "include \"library.alh\"\n",
|
|
|
+ "\n",
|
|
|
+ "Boolean function main(model : Element):\n",
|
|
|
+ " String input_value\n",
|
|
|
+ " Float start_time\n",
|
|
|
+ " String current_state\n",
|
|
|
+ " String old_state\n",
|
|
|
+ " Element transitions\n",
|
|
|
+ " String transition\n",
|
|
|
+ "\n",
|
|
|
+ " start_time = time()\n",
|
|
|
+ "\n",
|
|
|
+ " Element all_states\n",
|
|
|
+ " String element_name\n",
|
|
|
+ " all_states = allInstances(model, \"FSA/State\")\n",
|
|
|
+ " while (set_len(all_states) > 0):\n",
|
|
|
+ " element_name = set_pop(all_states)\n",
|
|
|
+ " if (read_type(model, element_name) == \"FSA/InitialState\"):\n",
|
|
|
+ " current_state = element_name\n",
|
|
|
+ " old_state = element_name\n",
|
|
|
+ " break!\n",
|
|
|
+ "\n",
|
|
|
+ " while (time() - start_time < 10.0):\n",
|
|
|
+ " if (has_input()):\n",
|
|
|
+ " input_value = list_read(string_split(input(), \"\\\\n\"), 0)\n",
|
|
|
+ "\n",
|
|
|
+ " transitions = allOutgoingAssociationInstances(model, current_state, \"FSA/Transition\")\n",
|
|
|
+ " while (set_len(transitions) > 0):\n",
|
|
|
+ " transition = set_pop(transitions)\n",
|
|
|
+ " if (cast_string(read_attribute(model, transition, \"trigger\")) == input_value):\n",
|
|
|
+ " if (element_neq(read_attribute(model, transition, \"raise\"), read_root())):\n",
|
|
|
+ " log(cast_value(time() - start_time) + \" output \" + cast_string(read_attribute(model, transition, \"raise\")))\n",
|
|
|
+ " output(cast_value(time() - start_time) + \" output \" + cast_string(read_attribute(model, transition, \"raise\")))\n",
|
|
|
+ " if (element_neq(read_attribute(model, transition, \"script\"), read_root())):\n",
|
|
|
+ " Element func\n",
|
|
|
+ " func = get_func_AL_model(import_node(read_attribute(model, transition, \"script\")))\n",
|
|
|
+ " func()\n",
|
|
|
+ " current_state = readAssociationDestination(model, transition)\n",
|
|
|
+ " break!\n",
|
|
|
+ "\n",
|
|
|
+ " log(cast_value(time() - start_time) + \" \" + cast_string(read_attribute(model, current_state, \"name\")))\n",
|
|
|
+ " sleep(0.2)\n",
|
|
|
+ " return True!\n",
|
|
|
+ " \"\"\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Now we can see it in action.\n",
|
|
|
+ "For now, we just rely on the end time of the simulation (and no inputs happen), but otherwise we would have to couple it to an SCCD model."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 25,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "data": {
|
|
|
+ "text/plain": [
|
|
|
+ "True"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ "execution_count": 25,
|
|
|
+ "metadata": {},
|
|
|
+ "output_type": "execute_result"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "model_add(\"models/my_FSA\", \"formalisms/MyOwnFSA\", \"\"\"\n",
|
|
|
+ " InitialState init{\n",
|
|
|
+ " name = \"initial\"\n",
|
|
|
+ " }\n",
|
|
|
+ " State s1{\n",
|
|
|
+ " name = \"S1\"\n",
|
|
|
+ " }\n",
|
|
|
+ " State s2{\n",
|
|
|
+ " name = \"S2\"\n",
|
|
|
+ " }\n",
|
|
|
+ " Transition (init, s1) {\n",
|
|
|
+ " }\n",
|
|
|
+ " Transition (s1, s2) {\n",
|
|
|
+ " trigger = \"A\"\n",
|
|
|
+ " }\n",
|
|
|
+ " \"\"\")\n",
|
|
|
+ "transformation_execute_AL(\"formalisms/MyOwnFSA_activities/simulate\", {\"FSA\": \"models/my_FSA\"}, {})"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "## Model Transformation"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Finally, it is possible to define a model transformation.\n",
|
|
|
+ "This requires RAMification and such, but this is all done transparently by the Modelverse.\n",
|
|
|
+ "Defining a model transformation is therefore identical to defining an Action Language activity, except that now we pass a model of transformations and rules, instead of passing an action language fragment.\n",
|
|
|
+ "\n",
|
|
|
+ "For our defined FSAs, assume that we want to add a simple optimization transformation, removing all states that have no incoming transition."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 26,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [],
|
|
|
+ "source": [
|
|
|
+ "transformation_add_MT({\"FSA\": \"formalisms/MyOwnFSA\"}, {\"FSA\": \"formalisms/MyOwnFSA\"}, \"formalisms/MyOwnFSA_activities/optimize\", \"\"\"\n",
|
|
|
+ "include \"primitives.alh\"\n",
|
|
|
+ "include \"modelling.alh\"\n",
|
|
|
+ "include \"object_operations.alh\"\n",
|
|
|
+ "\n",
|
|
|
+ "Composite schedule {\n",
|
|
|
+ " {Contains} Success success {}\n",
|
|
|
+ " {Contains} ForAll optimize {\n",
|
|
|
+ " NAC { \n",
|
|
|
+ " Pre_FSA/State nac_s_1 {\n",
|
|
|
+ " label = \"0\"\n",
|
|
|
+ " }\n",
|
|
|
+ " Pre_FSA/State nac_s_2 {\n",
|
|
|
+ " label = \"1\"\n",
|
|
|
+ " }\n",
|
|
|
+ " Pre_FSA/Transition nac_s_3 (nac_s_2, nac_s_1) {\n",
|
|
|
+ " label = \"2\"\n",
|
|
|
+ " }\n",
|
|
|
+ " }\n",
|
|
|
+ " LHS {\n",
|
|
|
+ " Pre_FSA/State pre_s_1 {\n",
|
|
|
+ " label = \"0\"\n",
|
|
|
+ " constraint = $\n",
|
|
|
+ " Boolean function not_initial(model : Element, name : String):\n",
|
|
|
+ " if (read_type(model, name) == \"FSA/InitialState\"):\n",
|
|
|
+ " return False!\n",
|
|
|
+ " else:\n",
|
|
|
+ " return True!\n",
|
|
|
+ " $\n",
|
|
|
+ " }\n",
|
|
|
+ " }\n",
|
|
|
+ " RHS {\n",
|
|
|
+ " }\n",
|
|
|
+ " } \n",
|
|
|
+ "}\n",
|
|
|
+ "\n",
|
|
|
+ "Initial (schedule, optimize) {}\n",
|
|
|
+ "OnSuccess (optimize, optimize) {}\n",
|
|
|
+ "OnFailure (optimize, success) {}\n",
|
|
|
+ " \"\"\")"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "Now we can see it in action."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 27,
|
|
|
+ "metadata": {},
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Before:\n",
|
|
|
+ "[{'__id': 'a', '__type': 'InitialState', 'name': 'A'}, {'__id': 'b', '__type': 'State', 'name': 'B'}, {'__id': 'c', '__type': 'State', 'name': 'C'}, {'__id': '__0', '__type': 'Transition', '__source': 'a', '__target': 'b', 'trigger': None, 'raise': None, 'script': {'AL': ''}}]\n",
|
|
|
+ "After:\n",
|
|
|
+ "[{'__id': 'a', '__type': 'InitialState', 'name': 'A'}, {'__id': 'b', '__type': 'State', 'name': 'B'}, {'__id': '__0', '__type': 'Transition', '__source': 'a', '__target': 'b', 'trigger': None, 'raise': None, 'script': {'AL': ''}}]\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "model_add(\"models/my_FSA\", \"formalisms/MyOwnFSA\", \"\"\"\n",
|
|
|
+ " InitialState a {\n",
|
|
|
+ " name = \"A\"\n",
|
|
|
+ " }\n",
|
|
|
+ " State b {\n",
|
|
|
+ " name = \"B\"\n",
|
|
|
+ " }\n",
|
|
|
+ " State c {\n",
|
|
|
+ " name = \"C\"\n",
|
|
|
+ " }\n",
|
|
|
+ " Transition (a, b) {}\n",
|
|
|
+ "\"\"\")\n",
|
|
|
+ "\n",
|
|
|
+ "print(\"Before:\")\n",
|
|
|
+ "print(all_instances(\"models/my_FSA\", \"State\"))\n",
|
|
|
+ "\n",
|
|
|
+ "transformation_execute_MT(\"formalisms/MyOwnFSA_activities/optimize\", {\"FSA\": \"models/my_FSA\"}, {\"FSA\": \"models/my_FSA\"})\n",
|
|
|
+ "\n",
|
|
|
+ "print(\"After:\")\n",
|
|
|
+ "print(all_instances(\"models/my_FSA\", \"State\"))"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "## Traceability Links"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "It is often useful to have multiple metamodels that integrate with one another.\n",
|
|
|
+ "For example, when defining denotational semantics, we might want to create traceability links between both formalisms.\n",
|
|
|
+ "As in the Modelverse everything must be explicitly modelled, these links should also follow the usual modelling conventions.\n",
|
|
|
+ "That is, the links must have a type defined.\n",
|
|
|
+ "For that purpose, the Modelverse create a *merged* metamodel on which the activities actually occur.\n",
|
|
|
+ "It is possible to define a callback in each of the *transformation_add_* operations, which are then able to alter this merged metamodel.\n",
|
|
|
+ "Such alterations can, for example, include adding a traceability link between elements from different origining metamodels.\n",
|
|
|
+ "For more details, refer to the documentation."
|
|
|
+ ]
|
|
|
}
|
|
|
],
|
|
|
"metadata": {
|