Просмотр исходного кода

Add atomic DEVS model library in the MV

Yentl Van Tendeloo 7 лет назад
Родитель
Сommit
ad91f4456d
3 измененных файлов с 464 добавлено и 1 удалено
  1. 2 0
      models/WSC/ADEVS.mvc
  2. 461 0
      models/WSC/pm_library.mvc
  3. 1 1
      models/pm_translate.py

+ 2 - 0
models/WSC/ADEVS.mvc

@@ -1,8 +1,10 @@
 SimpleAttribute PythonCode {}
 SimpleAttribute String {}
+SimpleAttribute Natural {}
 
 Class AtomicDEVSBlock {
     name : String
+    parameters : Natural
     timeAdvance: PythonCode
     outputFnc: PythonCode
     intTransition: PythonCode

+ 461 - 0
models/WSC/pm_library.mvc

@@ -0,0 +1,461 @@
+AtomicDEVSBlock ResourceHandler {
+    name = "ResourceHandler"
+
+    parameters = 1
+    initialState = "self.state, self.elapsed = {'resources': parameters[0], 'queue': []}, 0.0"
+
+    constructor = """
+            def __init__(self, resources):
+                AtomicDEVS.__init__(self, "__resource_handler")
+                self.state = {'resources': resources, 'queue': []}
+                self.elapsed = 0.0
+                self.resource_in = self.addInPort("resource_in")
+                self.resource_out = self.addOutPort("resource_out")
+        """
+
+    timeAdvance = """
+        if self.state['queue'] and self.state['resources']:
+            # Can grant a resource
+            return 0.0
+        else:
+            # No request queued, or no available resources to handle the request
+            return float('inf')
+        """
+
+    outputFnc = """
+        return {self.resource_out: {'id': self.state['queue'][0]}}
+        """
+
+    intTransition = """
+        # Processed a request that could be processed
+        self.state['resources'] -= 1
+        del self.state['queue'][0]
+        return self.state
+        """
+
+    extTransition = """
+        for inp in inputs[self.resource_in]:
+            if inp['type'] == "request":
+                # Queue the request
+                self.state['queue'].append(inp['id'])
+            elif inp['type'] == "release":
+                # Increment the number of available resources
+                self.state['resources'] += 1
+
+        return self.state
+        """
+}
+
+InputPort rh_ri {
+    name = "resource_in"
+}
+
+OutputPort rh_ro {
+    name = "resource_out"
+}
+
+DEVSBlockToPort (ResourceHandler, rh_ri) {}
+DEVSBlockToPort (ResourceHandler, rh_ro) {}
+
+AtomicDEVSBlock Activity {
+    name = "Activity"
+    parameters = 2
+    initialState = """
+        class ActivityState(object):
+            def __init__(self, name, distribution):
+                self.timer = float('inf')
+                self.mode = "inactive"
+                self.counter = 0
+                self.name = name
+                self.distribution = distribution
+
+            def __str__(self):
+                return str(vars(self))
+
+            def random_sample(self):
+                return self.distribution(self.counter)
+
+        self.state, self.elapsed = ActivityState(parameters[0], parameters[1]), 0.0
+        """
+    
+    timeAdvance = """
+        return self.state.timer
+        """
+
+    outputFnc = """
+        if self.state.mode == "active":
+            # Output the control token to the next model in line, and release the resources
+            return {self.control_out: {}, self.resource_out: [{'type': "release"}]}
+        elif self.state.mode == "request_resource":
+            # Output a request for resources with a specified ID (used to find out whether this was our request)
+            return {self.resource_out: [{'type': "request", 'id': "%s-%s" % (self.state.name, self.state.counter)}]}
+        else:
+            return {}
+        """
+
+    intTransition = """
+        self.state.timer -= self.timeAdvance()
+        if self.state.mode == "request_resource":
+            # Go and request the required resource
+            self.state.mode = "wait_resource"
+            self.state.timer = float('inf')
+        elif self.state.mode == "active":
+            # Finished execution, so release resources
+            self.state.mode = "inactive"
+            self.state.timer = 0.0
+            self.state.timer = float('inf')
+            self.state.counter += 1
+        return self.state
+        """
+
+    extTransition = """
+        self.state.timer -= self.elapsed
+        if self.state.mode == "inactive" and self.control_in in inputs:
+            # Got control token, so ask for the required resources
+            self.state.mode = "request_resource"
+            self.state.timer = 0.0
+            # NOTE this violates DEVS, though is easy to debug
+            #print("Activate " + str(self.state.name) + " at time " + str(self.time_last[0] + self.elapsed))
+        elif self.state.mode == "wait_resource" and self.resource_in in inputs and inputs[self.resource_in]['id'] == "%s-%s" % (self.state.name, self.state.counter):
+            # Got required resources, so start execution
+            self.state.mode = "active"
+            self.state.timer = self.state.random_sample()
+        return self.state
+        """
+}
+
+InputPort act_ri {
+    name = "resource_in"
+}
+
+OutputPort act_ro {
+    name = "resource_out"
+}
+
+DEVSBlockToPort (Activity, act_ri) {}
+DEVSBlockToPort (Activity, act_ro) {}
+
+AtomicDEVSBlock ParallelSplit {
+    name = "ParallelSplit"
+    parameters = 0
+
+    initialState = "self.state, self.elapsed = False, 0.0"
+
+    timeAdvance = """
+        if self.state:
+            return 0.0
+        else:
+            return float('inf')
+        """
+
+    outputFnc = """
+        return {self.control_out: {}}
+        """
+
+    intTransition = """
+        return False
+        """
+
+    extTransition = """
+        return True
+        """
+}
+
+InputPort split_ci {
+    name = "control_in"
+}
+
+OutputPort split_co {
+    name = "control_out"
+}
+
+DEVSBlockToPort (ParallelSplit, split_ci) {}
+DEVSBlockToPort (ParallelSplit, split_co) {}
+
+AtomicDEVSBlock ParallelSplit {
+    name = "ParallelSplit"
+    parameters = 0
+
+    initialState = "self.state, self.elapsed = False, 0.0"
+
+    timeAdvance = """
+        if self.state:
+            return 0.0
+        else:
+            return float('inf')
+        """
+
+    outputFnc = """
+        return {self.control_out: {}}
+        """
+
+    intTransition = """
+        return False
+        """
+
+    extTransition = """
+        return True
+        """
+}
+
+InputPort split_ci {
+    name = "control_in"
+}
+
+OutputPort split_co {
+    name = "control_out"
+}
+
+DEVSBlockToPort (ParallelSplit, split_ci) {}
+DEVSBlockToPort (ParallelSplit, split_co) {}
+
+AtomicDEVSBlock Synchronization {
+    name = "Synchronization"
+    parameters = 1
+
+    initialState = "self.state, self.elapsed = {'current': parameters[0], 'max': parameters[0]}, 0.0"
+
+    timeAdvance = """
+        if self.state['current'] == 0:
+            return 0.0
+        else:
+            return float('inf')
+        """
+
+    outputFnc = """
+        return {self.control_out: {}}
+        """
+
+    intTransition = """
+        self.state['current'] = self.state['max']
+        return self.state
+        """
+
+    extTransition = """
+        self.state['current'] -= 1
+        return self.state
+        """
+}
+
+InputPort syn_ci {
+    name = "control_in"
+}
+
+OutputPort syn_co {
+    name = "control_out"
+}
+
+DEVSBlockToPort (Synchronization, syn_ri) {}
+DEVSBlockToPort (Synchronization, syn_ro) {}
+
+AtomicDEVSBlock ExclusiveChoice {
+    name = "ExclusiveChoice"
+    parameters = 1
+
+    initialState = """
+        class ExclusiveChoiceState(object):
+            def __init__(self, distribution):
+                self.counter = 0
+                self.choice = None
+                self.distribution = distribution
+
+            def __str__(self):
+                return str(vars(self))
+
+            def make_choice(self):
+                return self.distribution(self.counter)
+
+        self.state, self.elapsed = ExclusiveChoiceState(parameters[0]), 0.0
+        """
+
+    timeAdvance = """
+        if self.state.choice is not None:
+            return 0.0
+        else:
+            return float('inf')
+        """
+
+    outputFnc = """
+        if self.state.choice == 0:
+            return {self.control_out1: {}}
+        else:
+            return {self.control_out2: {}}
+        """
+
+    intTransition = """
+        self.state.choice = None
+        self.state.counter += 1
+        return self.state
+        """
+
+    extTransition = """
+        # Got a control token, so have to make a choice
+        self.state.choice = self.state.make_choice()
+        return self.state
+        """
+}
+
+InputPort xor_ci {
+    name = "control_in"
+}
+
+OutputPort xor_co1 {
+    name = "control_out1"
+}
+
+OutputPort xor_co2 {
+    name = "control_out2"
+}
+
+DEVSBlockToPort (ExclusiveChoice, xor_ci) {}
+DEVSBlockToPort (ExclusiveChoice, xor_co1) {}
+DEVSBlockToPort (ExclusiveChoice, xor_co2) {}
+
+AtomicDEVSBlock SimpleMerge {
+    name = "SimpleMerge"
+    parameters = 0
+
+    initialState = "self.state, self.elapsed = False, 0.0"
+
+    timeAdvance = """
+        if self.state:
+            return 0.0
+        else:
+            return float('inf')
+        """
+
+    outputFnc = """
+        return {self.control_out: {}}
+        """
+
+    intTransition = """
+        return False
+        """
+
+    extTransition = """
+        return True
+        """
+}
+
+InputPort or_ci {
+    name = "control_in"
+}
+
+OutputPort or_co {
+    name = "control_out"
+}
+
+DEVSBlockToPort (SimpleMerge, or_ci) {}
+DEVSBlockToPort (SimpleMerge, or_co) {}
+
+AtomicDEVSBlock MultiInstance {
+    name = "MultiInstance"
+    parameters = 2
+
+    initialState = """
+        class MultiInstanceState(object):
+            def __init__(self, name, num, distribution):
+                self.spawned = num
+                self.collected = 0
+                self.counter = 0
+                self.mode = "inactive"
+                self.running_tasks = []
+                self.requested = []
+                self.name = name
+                self.distribution = distribution
+
+            def __str__(self):
+                return str(vars(self))
+
+            def task_time(self):
+                return self.distribution(self.counter)
+
+        self.state, self.elapsed = MultiInstanceState(self.name, parameters[0], parameters[1])
+        """
+
+    timeAdvance = """
+        if self.state.mode == "finish":
+            return 0.0
+        elif self.state.running_tasks:
+            return self.state.running_tasks[0][0]
+        elif self.state.mode == "request_resources":
+            return 0.0
+        else:
+            return float('inf')
+        """
+
+    outputFnc = """
+        if self.state.mode == "request_resources":
+            # Request all resources in one go
+            return {self.resource_out: [{'type': 'request', 'id': i} for i in self.state.requested]}
+        elif self.state.mode == "active":
+            # Finished an instance, so release it
+            return {self.resource_out: [{'type': 'release'}]}
+        elif self.state.mode == "finish":
+            # Finished execution of all, so pass on token
+            return {self.control_out: {}}
+        else:
+            return {}
+        """
+
+    intTransition = """
+        ta = self.timeAdvance()
+        for t in self.state.running_tasks:
+            t[0] -= ta
+
+        if self.state.mode == "active":
+            # Finished an instance, so pop it
+            del self.state.running_tasks[0]
+            self.state.collected += 1
+            if self.state.collected == self.state.spawned:
+                self.state.mode = "finish"
+        elif self.state.mode == "request_resources":
+            # Requested resources, so be ready for a response
+            self.state.mode = "active"
+        elif self.state.mode == "finish":
+            self.state.mode = "inactive"
+            self.state.collected = 0
+            self.state.counter += 1
+            self.state.running_tasks = []
+        return self.state
+        """
+
+    extTransition = """
+        # Got input, so have to spawn #num of them
+        for t in self.state.running_tasks:
+            t[0] -= self.elapsed
+
+        if self.state.mode == "inactive" and self.control_in in inputs:
+            self.state.mode = "request_resources"
+            self.state.requested = ["%s-%s-%s" % (self.state.name, self.state.counter, i) for i in range(self.state.spawned)]
+
+        if self.state.mode in ["active", "release_resource"] and self.resource_in in inputs:
+            # Got a resource, so allocate it to an activity
+            self.state.running_tasks.append([self.state.task_time(), self.state.requested.pop(0)])
+            # NOTE this violates DEVS, though is easy to debug
+            #print("Spawn " + str(self.state.running_tasks[-1][1]) + " at time " + str(self.time_last[0] + self.elapsed))
+            self.state.running_tasks.sort()
+        return self.state
+        """
+}
+
+InputPort mi_ci {
+    name = "control_in"
+}
+
+OutputPort mu_co {
+    name = "control_out"
+}
+
+InputPort mi_ri {
+    name = "resource_in"
+}
+
+OutputPort mu_ro {
+    name = "resource_out"
+}
+
+DEVSBlockToPort (MultiInstance, mi_ci) {}
+DEVSBlockToPort (MultiInstance, mi_co) {}
+DEVSBlockToPort (MultiInstance, mi_ri) {}
+DEVSBlockToPort (MultiInstance, mi_ro) {}

+ 1 - 1
models/pm_translate.py

@@ -12,12 +12,12 @@ model_add("formalisms/DEVS/DEVS_MM", "formalisms/SimpleClassDiagrams", open("mod
 model_add("formalisms/Metrics/Metrics_MM", "formalisms/SimpleClassDiagrams", open("models/WSC/metrics.mvc", 'r').read())
 model_add("formalisms/PM/PM_Extended_MM", "formalisms/SimpleClassDiagrams", open("models/WSC/pm.mvc", 'r').read())
 
-"""
 model_add("models/PM/to_DEVS", "formalisms/ProcessModel", open("models/WSC/pm_PM_to_DEVS.mvc").read())
 
 model_add("models/DEVS/PM_library", "formalisms/DEVS/ADEVS_MM", open("models/WSC/pm_library.mvc", 'r').read())
 model_add("models/PM/example_PM", "formalisms/PM/PM_Extended_MM", open("models/WSC/pm_example.mvc", 'r').read())
 
+"""
 transformation_add_MT("formalisms/PM/to_DEVS", {"PM": "formalisms/PM/PM_Extended_MM"}, {"ADEVS": "formalisms/DEVS/ADEVS_MM"}, open("models/WSC/PM_to_DEVS.mvc", 'r').read())
 transformation_add_AL("formalisms/DEVS/merge", {"ADEVS": "formalisms/DEVS/ADEVS_MM", "CDEVS": "formalisms/DEVS/CDEVS_MM"}, {"DEVS": "formalisms/DEVS/DEVS_MM"}, open("models/WSC/DEVS_merge.alc", 'r').read())
 transformation_add_AL("formalisms/DEVS/simulate", {"DEVS": "formalisms/DEVS/DEVS_MM"}, {"metrics": "formalisms/Metrics/Metrics_MM"}, open("models/WSC/DEVS_simulate.alc", 'r').read())