pyjevsim 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyjevsim/__init__.py +41 -0
- pyjevsim/atomic_model.py +39 -0
- pyjevsim/behavior_executor.py +126 -0
- pyjevsim/behavior_model.py +260 -0
- pyjevsim/core_model.py +103 -0
- pyjevsim/default_message_catcher.py +42 -0
- pyjevsim/definition.py +102 -0
- pyjevsim/executor.py +27 -0
- pyjevsim/executor_factory.py +77 -0
- pyjevsim/exgen.py +116 -0
- pyjevsim/message_deliverer.py +44 -0
- pyjevsim/restore_handler.py +116 -0
- pyjevsim/snapshot_condition.py +101 -0
- pyjevsim/snapshot_executor.py +219 -0
- pyjevsim/snapshot_factory.py +63 -0
- pyjevsim/snapshot_manager.py +120 -0
- pyjevsim/structural_executor.py +136 -0
- pyjevsim/structural_model.py +48 -0
- pyjevsim/system_executor.py +648 -0
- pyjevsim/system_message.py +99 -0
- pyjevsim/system_object.py +52 -0
- pyjevsim/termination_manager.py +37 -0
- pyjevsim-1.0.0.dist-info/LICENSE +21 -0
- pyjevsim-1.0.0.dist-info/METADATA +160 -0
- pyjevsim-1.0.0.dist-info/RECORD +27 -0
- pyjevsim-1.0.0.dist-info/WHEEL +5 -0
- pyjevsim-1.0.0.dist-info/top_level.txt +1 -0
pyjevsim/definition.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Changbeom Choi (@cbchoi)
|
|
3
|
+
Copyright (c) 2014-2020 Handong Global University
|
|
4
|
+
Copyright (c) 2021-2024 Hanbat National University
|
|
5
|
+
License: MIT. The full license text is available at:
|
|
6
|
+
https://github.com/eventsim/pyjevsim/blob/main/LICENSE
|
|
7
|
+
|
|
8
|
+
This module contains definitions for pyjevsim's const and type.
|
|
9
|
+
"""
|
|
10
|
+
from enum import Enum
|
|
11
|
+
|
|
12
|
+
# Define an infinite value
|
|
13
|
+
Infinite = float("inf")
|
|
14
|
+
|
|
15
|
+
class AttributeType(Enum):
|
|
16
|
+
"""Enum for attribute types."""
|
|
17
|
+
ASPECT = 1
|
|
18
|
+
RUNTIME = 2
|
|
19
|
+
UNKNOWN_TYPE = -1
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def resolve_type_from_str(name):
|
|
23
|
+
"""Resolves an attribute type from a string.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
name (str): The name of the attribute type
|
|
27
|
+
Returns:
|
|
28
|
+
AttributeType: The resolved attribute type
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
if "ASPECT" == name.upper():
|
|
32
|
+
return AttributeType.ASPECT
|
|
33
|
+
elif "RUNTIME" == name.upper():
|
|
34
|
+
return AttributeType.RUNTIME
|
|
35
|
+
else:
|
|
36
|
+
return AttributeType.UNKNOWN_TYPE
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def resolve_type_from_enum(enum):
|
|
40
|
+
"""Resolves an attribute type to a string.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
enum (AttributeType): The attribute type enum
|
|
44
|
+
Returns:
|
|
45
|
+
str: The name of the attribute type
|
|
46
|
+
"""
|
|
47
|
+
if enum == AttributeType.ASPECT:
|
|
48
|
+
return "ASPECT"
|
|
49
|
+
elif enum == AttributeType.RUNTIME:
|
|
50
|
+
return "RUNTIME"
|
|
51
|
+
else:
|
|
52
|
+
return "UNKNOWN"
|
|
53
|
+
|
|
54
|
+
class SimulationMode(Enum):
|
|
55
|
+
"""Enum for simulation modes."""
|
|
56
|
+
|
|
57
|
+
SIMULATION_IDLE = (
|
|
58
|
+
0 # Simulation Engine is instantiated but simulation is not running
|
|
59
|
+
)
|
|
60
|
+
SIMULATION_RUNNING = 1 # Simulation Engine is instantiated, simulation is running
|
|
61
|
+
SIMULATION_TERMINATED = (
|
|
62
|
+
2 # Simulation Engine is instantiated but simulation is terminated
|
|
63
|
+
)
|
|
64
|
+
SIMULATION_PAUSE = 3 # Simulation Engine is instantiated, simulation paused
|
|
65
|
+
SIMULATION_UNKNOWN = -1 # Simulation Engine went to abnormal state
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class ModelType(Enum):
|
|
69
|
+
"""Enum for model types."""
|
|
70
|
+
|
|
71
|
+
BEHAVIORAL = 0 #BehaviorModel type : DEVS Atomic Model
|
|
72
|
+
STRUCTURAL = 1 #StructuralModel type : DEVS Coupled Model
|
|
73
|
+
UTILITY = 2
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ExecutionType(Enum):
|
|
77
|
+
"""Enum for execution types."""
|
|
78
|
+
|
|
79
|
+
R_TIME = 0 #Real time
|
|
80
|
+
V_TIME = 1 #Virtual time
|
|
81
|
+
HLA_TIME = 2 #HLA/RTI-controlled time (externally driven)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class SingletonType(object):
|
|
85
|
+
"""A decorator for making a class a singleton."""
|
|
86
|
+
|
|
87
|
+
def __call__(self, cls, *args, **kwargs):
|
|
88
|
+
"""Creates or returns the singleton instance of the class.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
cls (type): The class to be instantiated
|
|
92
|
+
*args: Variable length argument list
|
|
93
|
+
**kwargs: Arbitrary keyword arguments
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
object: The singleton instance of the class
|
|
97
|
+
"""
|
|
98
|
+
try:
|
|
99
|
+
return cls.__instance
|
|
100
|
+
except AttributeError:
|
|
101
|
+
cls.__instance = super(SingletonType, cls).__call__(*args, **kwargs)
|
|
102
|
+
return cls.__instance
|
pyjevsim/executor.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Changbeom Choi (@cbchoi)
|
|
3
|
+
Copyright (c) 2014-2020 Handong Global University
|
|
4
|
+
Copyright (c) 2021-2024 Hanbat National University
|
|
5
|
+
License: MIT. The full license text is available at:
|
|
6
|
+
https://github.com/eventsim/pyjevsim/blob/main/LICENSE
|
|
7
|
+
|
|
8
|
+
This module contains Executor, the parent class of all Executor Types.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
class Executor:
|
|
12
|
+
"""Base class for executors."""
|
|
13
|
+
def __init__(self, itime, dtime, ename, model, parent):
|
|
14
|
+
"""
|
|
15
|
+
Args:
|
|
16
|
+
itime (float): Instance creation time
|
|
17
|
+
dtime (float): Destruction time
|
|
18
|
+
ename (str): Engine name
|
|
19
|
+
"""
|
|
20
|
+
self.engine_name = ename
|
|
21
|
+
self._instance_t = itime
|
|
22
|
+
self._destruct_t = dtime
|
|
23
|
+
self.model = model
|
|
24
|
+
self.parent = parent
|
|
25
|
+
|
|
26
|
+
def __lt__(self, other):
|
|
27
|
+
return (self.request_time, self.get_obj_id()) < (other.request_time, other.get_obj_id())
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Changbeom Choi (@cbchoi)
|
|
3
|
+
Copyright (c) 2014-2020 Handong Global University
|
|
4
|
+
Copyright (c) 2021-2024 Hanbat National University
|
|
5
|
+
License: MIT. The full license text is available at:
|
|
6
|
+
https://github.com/eventsim/pyjevsim/blob/main/LICENSE
|
|
7
|
+
|
|
8
|
+
This module contains an ExecutorFactory that decorates an object of type Model into an Executor that is executable by a SysExecutor.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .definition import ModelType
|
|
12
|
+
from .behavior_executor import BehaviorExecutor
|
|
13
|
+
|
|
14
|
+
class ExecutorFactory:
|
|
15
|
+
"""Factory class to create different types of executors."""
|
|
16
|
+
|
|
17
|
+
def __init__(self):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
def create_executor(self, global_time, ins_t, des_t, en_name, model, parent
|
|
21
|
+
):
|
|
22
|
+
"""Creates an executor based on the model type.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
global_time (float): Global simulation time
|
|
26
|
+
ins_t (float): Instance creation time
|
|
27
|
+
des_t (float): Destruction time
|
|
28
|
+
en_name (str): Engine name
|
|
29
|
+
model(ModelType.BEHAVIORAL of ModelType.STRUCTURAL): The model to execute
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Executor: The created executor
|
|
33
|
+
"""
|
|
34
|
+
if model.get_model_type() == ModelType.BEHAVIORAL:
|
|
35
|
+
return self.create_behavior_executor(
|
|
36
|
+
global_time, ins_t, des_t, en_name, model, parent
|
|
37
|
+
)
|
|
38
|
+
elif model.get_model_type() == ModelType.STRUCTURAL:
|
|
39
|
+
return self.create_structural_executor(
|
|
40
|
+
global_time, ins_t, des_t, en_name, model, parent
|
|
41
|
+
)
|
|
42
|
+
else:
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
def create_behavior_executor(self, _, ins_t, des_t, en_name, model, parent):
|
|
46
|
+
"""Create BehaviorModelexecutor
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
_ (float): Unused global time
|
|
50
|
+
ins_t (float): Instance creation time
|
|
51
|
+
des_t (float): Destruction time
|
|
52
|
+
en_name (str): SysExecutor name
|
|
53
|
+
model (BehaviorModel): Behavior model to execute
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
BehaviorModelExecutor: The created BehaviorModelexecutor
|
|
57
|
+
"""
|
|
58
|
+
return BehaviorExecutor(ins_t, des_t, en_name, model, parent)
|
|
59
|
+
|
|
60
|
+
def create_structural_executor(self, global_time, ins_t, des_t, en_name, model, parent):
|
|
61
|
+
"""Create StructuralModelExecutor
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
global_time (float): Global simulation time
|
|
65
|
+
ins_t (float): Instance creation time
|
|
66
|
+
des_t (float): Destruction time
|
|
67
|
+
en_name (str): SysExecutor name
|
|
68
|
+
model (StructuralModel): StructuralModel to execute
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
StructuralModelExecutor: created StructuralModelExecutor
|
|
72
|
+
"""
|
|
73
|
+
from .structural_executor import StructuralExecutor
|
|
74
|
+
return StructuralExecutor(
|
|
75
|
+
global_time, ins_t, des_t, en_name, model, parent, self
|
|
76
|
+
)
|
|
77
|
+
|
pyjevsim/exgen.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
relay_example = """from pyjevsim import BehaviorModel, SysExecutor, SysMessage, Infinite, ExecutionType
|
|
2
|
+
import datetime
|
|
3
|
+
|
|
4
|
+
class PEG(BehaviorModel):
|
|
5
|
+
def __init__(self, name):
|
|
6
|
+
BehaviorModel.__init__(self, name)
|
|
7
|
+
self.init_state("Wait")
|
|
8
|
+
self.insert_state("Wait", Infinite)
|
|
9
|
+
self.insert_state("Generate", 1)
|
|
10
|
+
|
|
11
|
+
self.insert_input_port("start")
|
|
12
|
+
self.insert_output_port("process")
|
|
13
|
+
|
|
14
|
+
def ext_trans(self, port, msg):
|
|
15
|
+
if port == "start":
|
|
16
|
+
print(f"[Gen][IN]: {datetime.datetime.now()}")
|
|
17
|
+
self._cur_state = "Generate"
|
|
18
|
+
|
|
19
|
+
def output(self, msg_deliver):
|
|
20
|
+
msg = SysMessage(self.get_name(), "process")
|
|
21
|
+
msg.insert(f"[Gen][OUT]: {datetime.datetime.now()}")
|
|
22
|
+
msg_deliver.insert_message(msg)
|
|
23
|
+
|
|
24
|
+
def int_trans(self):
|
|
25
|
+
if self._cur_state == "Generate":
|
|
26
|
+
self._cur_state = "Generate"
|
|
27
|
+
|
|
28
|
+
class MsgRecv(BehaviorModel):
|
|
29
|
+
def __init__(self, name):
|
|
30
|
+
BehaviorModel.__init__(self, name)
|
|
31
|
+
|
|
32
|
+
self.init_state("Wait")
|
|
33
|
+
self.insert_state("Wait", Infinite)
|
|
34
|
+
self.insert_input_port("recv")
|
|
35
|
+
|
|
36
|
+
def ext_trans(self, port, msg):
|
|
37
|
+
if port == "recv":
|
|
38
|
+
print(f"[MsgRecv][IN]: {datetime.datetime.now()}")
|
|
39
|
+
data = msg.retrieve()
|
|
40
|
+
print(data[0])
|
|
41
|
+
self._cur_state = "Wait"
|
|
42
|
+
|
|
43
|
+
def output(self, msg_deliver):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
def int_trans(self):
|
|
47
|
+
if self._cur_state == "Wait":
|
|
48
|
+
self._cur_state = "Wait"
|
|
49
|
+
|
|
50
|
+
# System Executor Initialization
|
|
51
|
+
se = SysExecutor(1, ex_mode=ExecutionType.R_TIME)
|
|
52
|
+
se.insert_input_port("start")
|
|
53
|
+
gen = PEG("Gen")
|
|
54
|
+
se.register_entity(gen)
|
|
55
|
+
proc = MsgRecv("Proc")
|
|
56
|
+
se.register_entity(proc)
|
|
57
|
+
se.coupling_relation(None, "start", gen, "start")
|
|
58
|
+
se.coupling_relation(gen, "process", proc, "recv")
|
|
59
|
+
se.insert_external_event("start", None)
|
|
60
|
+
se.simulate(5)
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
periodic_example = """from pyjevsim import BehaviorModel, SysExecutor, Infinite, ExecutionType
|
|
64
|
+
import datetime
|
|
65
|
+
|
|
66
|
+
class PEx(BehaviorModel):
|
|
67
|
+
def __init__(self, name):
|
|
68
|
+
BehaviorModel.__init__(self, name)
|
|
69
|
+
self.init_state("Wait")
|
|
70
|
+
self.insert_state("Wait", Infinite)
|
|
71
|
+
self.insert_state("Generate", 1)
|
|
72
|
+
|
|
73
|
+
self.insert_input_port("start")
|
|
74
|
+
|
|
75
|
+
def ext_trans(self, port, msg):
|
|
76
|
+
if port == "start":
|
|
77
|
+
print(f"[Gen][IN]: {datetime.datetime.now()}")
|
|
78
|
+
self._cur_state = "Generate"
|
|
79
|
+
|
|
80
|
+
def output(self, msg_deliver):
|
|
81
|
+
print(f"[Gen][OUT]: {datetime.datetime.now()}")
|
|
82
|
+
|
|
83
|
+
def int_trans(self):
|
|
84
|
+
if self._cur_state == "Generate":
|
|
85
|
+
self._cur_state = "Generate"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
se = SysExecutor(1, ex_mode=ExecutionType.R_TIME)
|
|
89
|
+
se.insert_input_port("start")
|
|
90
|
+
gen = PEx("Gen")
|
|
91
|
+
se.register_entity(gen)
|
|
92
|
+
se.coupling_relation(None, "start", gen, "start")
|
|
93
|
+
se.insert_external_event("start", None)
|
|
94
|
+
se.simulate(5)
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
usage = """
|
|
98
|
+
Usage: python -m pyjevsim.exgen [example]
|
|
99
|
+
|
|
100
|
+
types of example:
|
|
101
|
+
periodic:\t Prints event log periodically
|
|
102
|
+
relay: \t A model sends an output event and another model receives the event
|
|
103
|
+
"""
|
|
104
|
+
import sys
|
|
105
|
+
if len(sys.argv) != 2:
|
|
106
|
+
print(usage)
|
|
107
|
+
elif sys.argv[1] == "relay":
|
|
108
|
+
with open("example_relay.py", "w") as f:
|
|
109
|
+
f.write(relay_example)
|
|
110
|
+
print("Generated: example_relay.py")
|
|
111
|
+
elif sys.argv[1] == "periodic":
|
|
112
|
+
with open("example_periodic.py", "w") as f:
|
|
113
|
+
f.write(periodic_example)
|
|
114
|
+
print("Generated: example_periodic.py")
|
|
115
|
+
else:
|
|
116
|
+
print(usage)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from .definition import *
|
|
2
|
+
from .system_message import SysMessage
|
|
3
|
+
|
|
4
|
+
class MessageDeliverer:
|
|
5
|
+
def __init__(self):
|
|
6
|
+
self.data_list = []
|
|
7
|
+
|
|
8
|
+
def insert_message(self, msg):
|
|
9
|
+
"""
|
|
10
|
+
Inserts a message into the data list.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
msg: Message object to be inserted.
|
|
14
|
+
"""
|
|
15
|
+
self.data_list.append(msg) #SysMessage type
|
|
16
|
+
|
|
17
|
+
#self.data_list.sort(key=lambda m: m.get_scheduled_time())
|
|
18
|
+
|
|
19
|
+
def has_contents(self):
|
|
20
|
+
"""
|
|
21
|
+
Checks if the data list contains any messages.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
bool: True if the list is not empty, otherwise False.
|
|
25
|
+
"""
|
|
26
|
+
return len(self.data_list) > 0
|
|
27
|
+
|
|
28
|
+
def get_contents(self):
|
|
29
|
+
"""
|
|
30
|
+
Retrieves the list of messages.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
list: The list of Message objects.
|
|
34
|
+
"""
|
|
35
|
+
return self.data_list
|
|
36
|
+
|
|
37
|
+
def get_first_event_time(self):
|
|
38
|
+
"""
|
|
39
|
+
Retrieves the scheduled time of the first message in the list.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
float: Scheduled time of the first message or Infinity if the list is empty.
|
|
43
|
+
"""
|
|
44
|
+
return float("inf") if not self.data_list else self.data_list[0].get_scheduled_time()
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Changbeom Choi (@cbchoi)
|
|
3
|
+
Copyright (c) 2014-2020 Handong Global University
|
|
4
|
+
Copyright (c) 2021-2024 Hanbat National University
|
|
5
|
+
License: MIT. The full license text is available at:
|
|
6
|
+
https://github.com/eventsim/pyjevsim/blob/main/LICENSE
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
from dill import load, loads
|
|
10
|
+
from .definition import ModelType, ExecutionType
|
|
11
|
+
import json
|
|
12
|
+
import ast
|
|
13
|
+
from .system_executor import SysExecutor
|
|
14
|
+
|
|
15
|
+
class RestoreHandler():
|
|
16
|
+
""" Restore a snapshotted model or project.
|
|
17
|
+
"""
|
|
18
|
+
def __init__(self, t_resol=1, ex_mode=ExecutionType.V_TIME, name="project", path="./snapshot"):
|
|
19
|
+
"""
|
|
20
|
+
Initializes the RestoreHandler with time resolution, execution mode, name, and path.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
t_resol (float): Time resolution
|
|
24
|
+
ex_mode (R_TIME or V_TIME): Execution mode(Real time or Virtual time)
|
|
25
|
+
name (str): Name of SysExecutor
|
|
26
|
+
path (str, optional): Path to load snapshots
|
|
27
|
+
"""
|
|
28
|
+
self.path = f"{path}/{name}"
|
|
29
|
+
self.sim_name = name
|
|
30
|
+
self.engine = SysExecutor(t_resol, name, ex_mode, snapshot_manager=None)
|
|
31
|
+
self.model_map = {}
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
def restore_engine(self):
|
|
35
|
+
"""
|
|
36
|
+
Sets up SysExecutor with the relation map and model map.
|
|
37
|
+
"""
|
|
38
|
+
with open(f"{self.path}/relation_map.json", "r") as f:
|
|
39
|
+
relation = json.load(f)
|
|
40
|
+
relation = {ast.literal_eval(key): ast.literal_eval(value) for key, value in relation.items()}
|
|
41
|
+
|
|
42
|
+
model_list = {}
|
|
43
|
+
with open(f"{self.path}/model_map.json", "r") as f:
|
|
44
|
+
model_list = json.load(f)
|
|
45
|
+
model_list = model_list["model_name"]
|
|
46
|
+
|
|
47
|
+
self.load_models(model_list)
|
|
48
|
+
self.relations(relation)
|
|
49
|
+
|
|
50
|
+
def load_models(self, model_list):
|
|
51
|
+
"""
|
|
52
|
+
Loads models from files and registers them with SysExecutor.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
model_list (list): List of model names
|
|
56
|
+
"""
|
|
57
|
+
for model_name in model_list:
|
|
58
|
+
with open(f"{self.path}/{model_name}.simx", "rb") as f:
|
|
59
|
+
model = load(f)
|
|
60
|
+
|
|
61
|
+
self.model_map[model_name] = model["data"]
|
|
62
|
+
self.engine.register_entity(model["data"])
|
|
63
|
+
|
|
64
|
+
def relations(self, relation_map):
|
|
65
|
+
"""
|
|
66
|
+
Sets up coupling relations in SysExecutor.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
relation_map (dict): The relation map / 관계 맵
|
|
70
|
+
"""
|
|
71
|
+
for key, value in relation_map.items():
|
|
72
|
+
if key[0] in self.model_map.keys():
|
|
73
|
+
output_model = self.model_map[key[0]]
|
|
74
|
+
else:
|
|
75
|
+
output_model = self.engine
|
|
76
|
+
for model in value:
|
|
77
|
+
if model[0]:
|
|
78
|
+
input_model = self.model_map[model[0]]
|
|
79
|
+
else:
|
|
80
|
+
input_model = self.engine
|
|
81
|
+
self.engine.coupling_relation(output_model, key[1], input_model, model[1])
|
|
82
|
+
|
|
83
|
+
def get_engine(self):
|
|
84
|
+
"""Returns the SysExecutor.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Restored SysExecutor
|
|
88
|
+
"""
|
|
89
|
+
self.restore_engine()
|
|
90
|
+
return self.engine
|
|
91
|
+
|
|
92
|
+
def load_snapshot(self, name, shotmodel):
|
|
93
|
+
"""Loads BehaviorModel.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
name (str): The name of Model
|
|
97
|
+
shotmodel (bytes): Binary data of the model snapshot
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
object(BehaivorModel): The loaded model
|
|
101
|
+
|
|
102
|
+
Raises:
|
|
103
|
+
Exception: If the model type is not ModelType.BEHAVIORAL
|
|
104
|
+
"""
|
|
105
|
+
model_info = loads(shotmodel)
|
|
106
|
+
|
|
107
|
+
if model_info["type"] != ModelType.BEHAVIORAL and model_info["type"] != ModelType.STRUCTURAL :
|
|
108
|
+
raise Exception(f"{model_info['name']} is not of Model type")
|
|
109
|
+
|
|
110
|
+
model = model_info["data"]
|
|
111
|
+
|
|
112
|
+
if name is not None:
|
|
113
|
+
model.set_name(name)
|
|
114
|
+
|
|
115
|
+
return model
|
|
116
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: Changbeom Choi (@cbchoi)
|
|
3
|
+
Copyright (c) 2014-2020 Handong Global University
|
|
4
|
+
Copyright (c) 2021-2024 Hanbat National University
|
|
5
|
+
License: MIT. The full license text is available at:
|
|
6
|
+
https://github.com/eventsim/pyjevsim/blob/main/LICENSE
|
|
7
|
+
"""
|
|
8
|
+
from abc import abstractmethod, abstractstaticmethod
|
|
9
|
+
|
|
10
|
+
class SnapshotCondition:
|
|
11
|
+
"""A class for filling in the snapshot condition of a model.
|
|
12
|
+
Users inherit from SnapshotCondition to fill in the model snapshot condition.
|
|
13
|
+
Snapshot conditions can be placed before or after functions in the behavior model.
|
|
14
|
+
"""
|
|
15
|
+
@abstractstaticmethod
|
|
16
|
+
def create_executor(behavior_executor) :
|
|
17
|
+
"""
|
|
18
|
+
This method is an abstractstatic method.
|
|
19
|
+
Specify the SnapshotCondition you created as the return value of this method.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
behavior_executor (BehaviorExecutor): Set the BehaviorExecutor of the BehaviorModel you want to snapshot.
|
|
23
|
+
Returns:
|
|
24
|
+
SnapshotCondition : Returns the SnapshotCondition as configured by the user.
|
|
25
|
+
"""
|
|
26
|
+
return SnapshotCondition(behavior_executor)
|
|
27
|
+
|
|
28
|
+
def __init__(self, behavior_executor):
|
|
29
|
+
"""
|
|
30
|
+
Args:
|
|
31
|
+
behavior_executor (BehaviorExecutor): Set the BehaviorExecutor of the BehaviorModel you want to snapshot.
|
|
32
|
+
"""
|
|
33
|
+
self.behavior_executor = behavior_executor
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def snapshot_time_condition(self, global_time):
|
|
37
|
+
"""Abstract method for snapshot time condition.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
global_time (float): The global time / simulation time
|
|
41
|
+
"""
|
|
42
|
+
return False
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def snapshot_pre_condition_ext(self, port, msg, cur_state):
|
|
46
|
+
"""Abstract method for pre-condition of external transition snapshot.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
port (str): The port name
|
|
50
|
+
msg (SysMessage): The message
|
|
51
|
+
cur_state (str): The current state
|
|
52
|
+
"""
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
@abstractmethod
|
|
56
|
+
def snapshot_post_condition_ext(self, port, msg, cur_state):
|
|
57
|
+
"""Abstract method for post-condition of external transition snapshot.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
port (str): The port name
|
|
61
|
+
msg (SysMessage): The message
|
|
62
|
+
cur_state (str): The current state
|
|
63
|
+
"""
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def snapshot_pre_condition_int(self, cur_state):
|
|
68
|
+
"""Abstract method for pre-condition of internal transition snapshot.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
cur_state (str): The current state
|
|
72
|
+
"""
|
|
73
|
+
return False
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def snapshot_post_condition_int(self, cur_state):
|
|
77
|
+
"""Abstract method for post-condition of internal transition snapshot.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
cur_state (str): The current state
|
|
81
|
+
"""
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
@abstractmethod
|
|
85
|
+
def snapshot_pre_condition_out(self, cur_state):
|
|
86
|
+
"""Abstract method for pre-condition of output snapshot.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
cur_state (str): The current state
|
|
90
|
+
"""
|
|
91
|
+
return False
|
|
92
|
+
|
|
93
|
+
@abstractmethod
|
|
94
|
+
def snapshot_post_condition_out(self, msg, cur_state):
|
|
95
|
+
"""Abstract method for post-condition of output snapshot.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
msg (SysMessage): The message
|
|
99
|
+
cur_state (str): The current state
|
|
100
|
+
"""
|
|
101
|
+
return False
|