123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- include "primitives.alh"
- include "modelling.alh"
- include "object_operations.alh"
- include "utils.alh"
- include "random.alh"
- Void function print_states(model : Element, data : Element):
- Element classes
- Element states
- Element class
- String state
- log("Current states:")
- classes = set_copy(data["classes"])
- while (read_nr_out(classes) > 0):
- class = set_pop(classes)
- log(string_join(string_join(string_join(" ", class["ID"]), " : "), read_attribute(model, class["type"], "name")))
- states = set_copy(class["states"])
- while (read_nr_out(states) > 0):
- state = set_pop(states)
- log(string_join(" ", read_attribute(model, state, "name")))
- return!
- Element function filter(model : Element, set : Element, attribute_name : String, attribute_value : Element):
- Element keys
- String key
- Element result
- result = create_node()
- while (read_nr_out(set) > 0):
- key = set_pop(set)
- if (value_eq(read_attribute(model, key, attribute_name), attribute_value)):
- set_add(result, key)
- return result!
- Element function expand_state(model : Element, state : String):
- String t
- t = read_type(model, state)
- if (t == "SCCD/CompositeState"):
- // Recurse further in the composite
- return expand_composite_state(model, state)!
- elif (t == "SCCD/ParallelState"):
- // Split up all components
- return expand_parallel_state(model, state)!
- else:
- // Probably just an atomic, so return this one only
- Element result
- result = create_node()
- set_add(result, state)
- return result!
- Element function expand_composite_state(model : Element, composite_state : String):
- // Resolve all initial states from a single composite state
- String initial
- // Fetch the initial state
- initial = set_pop(filter(model, allAssociationDestinations(model, composite_state, "SCCD/composite_children"), "isInitial", True))
- // Expand the initial state, depending on what it is
- return expand_state(model, initial)!
- Element function expand_parallel_state(model : Element, parallel_state : String):
- // Resolve all initial states from a single parallel state
- Element children
- Element result
- Element expanded_children
- children = allAssociationDestinations(model, parallel_state, "SCCD/parallel_children")
- result = create_node()
- while (read_nr_out(children) > 0):
- set_merge(result, expand_state(model, set_pop(children)))
- return result!
- Void function start_class(model : Element, data : Element, class : String):
- // Start up the class and assign its initial state to it
- // Create the data structure for a running class
- Element class_handle
- class_handle = create_node()
- dict_add(class_handle, "type", class)
- dict_add(class_handle, "ID", cast_id2s(create_node()))
- // Add the current state of the class
- String initial_state
- // Should only be one behaviour linked to it!
- initial_state = set_pop(allAssociationDestinations(model, class, "SCCD/behaviour"))
- dict_add(class_handle, "states", expand_state(model, initial_state))
- // Add all attributes
- Element attributes
- attributes = create_node()
- Element attrs
- attrs = allAssociationDestinations(model, class, "SCCD/class_attributes")
- while (read_nr_out(attrs) > 0):
- dict_add(attributes, read_attribute(model, set_pop(attrs), "name"), create_node())
- dict_add(class_handle, "attributes", attributes)
- set_add(data["classes"], class_handle)
- return!
- Element function get_enabled_transitions(model : Element, state : String, interrupt : Element):
- // Returns all enabled transitions
- // TODO ignore conditions and afters
- Element result
- Element to_filter
- String attr
- String transition
- Element cond
- result = create_node()
- to_filter = allOutgoingAssociationInstances(model, state, "SCCD/transition")
- while (read_nr_out(to_filter) > 0):
- transition = set_pop(to_filter)
- attr = read_attribute(model, transition, "event")
- if (bool_or(element_eq(attr, read_root()), value_eq(attr, interrupt))):
- // Event is OK
- cond = read_attribute(model, transition, "cond")
- log("Resolved condition")
- if (element_neq(cond, read_root())):
- log("Result = " + cast_e2s(cond))
- cond = get_func_AL_model(cond)
- log("Resolved = " + cast_e2s(cond))
- // Execute condition
- if (bool_not(cond(create_node()))):
- log("Evaluated to True")
- // Condition false, so skip
- continue!
- else:
- log("Evaluated to False")
- else:
- log("NO condition")
- // Condition is OK
- set_add(result, transition)
- return result!
- Float function step_class(model : Element, data : Element, class : Element, interrupt : Element):
- // Find enabled transitions in a class and execute it, updating the state
- // Iterate over all current states, searching for enabled transitions
- // Search for enabled transitions in higher levels as well!
- Element states
- Element new_states
- String state
- Element transitions
- String transition
- Float t_min
- Float t_current
- states = set_copy(class["states"])
- new_states = create_node()
- while (read_nr_out(states) > 0):
- state = set_pop(states)
- // Fetch transitions in this state specifically (NO parent)
- transitions = get_enabled_transitions(model, state, interrupt)
- if (read_nr_out(transitions) != 0):
- // Found an enabled transition, so store that one
- transition = random_choice(transitions)
- set_merge(new_states, expand_state(model, readAssociationDestination(model, transition)))
- else:
- // Try going to the parent
- // TODO
- // Nothing found, so stay in the current state
- set_add(new_states, state)
- // Update states
- dict_overwrite(class, "states", new_states)
- return 1.0!
- Float function step(model : Element, data : Element, interrupt : Element):
- // Step through all classes
- Element classes
- Element class
- Float t_min
- Float t_class
- t_min = 99999.0
- classes = set_copy(data["classes"])
- while (read_nr_out(classes) > 0):
- class = set_pop(classes)
- t_class = step_class(model, data, class, interrupt)
- if (t_class < t_min):
- t_min = t_class
- return t_min!
- Boolean function main(model : Element):
- // Executes the provided SCCD model
- Element data
- data = create_node()
- dict_add(data, "classes", create_node())
- // Prepare for input
- output("Ready for input!")
- // Find initial
- String default_class
- default_class = set_pop(filter(model, allInstances(model, "SCCD/Class"), "default", True))
- // Start up the default class
- start_class(model, data, default_class)
- Float timeout
- Element interrupt
- timeout = 0.0
- while (True):
- print_states(model, data)
- interrupt = input_timeout(timeout)
- if (value_eq(interrupt, "#EXIT#")):
- // Stop execution
- return True!
- if (element_neq(interrupt, read_root())):
- // Got interrupt
- log("Got event: " + cast_v2s(interrupt))
- output("Processed event, ready for more!")
- timeout = step(model, data, interrupt)
- // We should never get here!
- return False!
|