import sys sys.path.append("../kernel/") sys.path.append("../state/") from modelverse_state.main import ModelverseState as MvS from modelverse_kernel.main import ModelverseKernel as MvK from pypdevs.DEVS import AtomicDEVS, CoupledDEVS from pypdevs.simulator import Simulator import json def translate(operation): return { "CN": "create_node", "CE": "create_edge", "CNV": "create_nodevalue", "CD": "create_dict", "RV": "read_value", "RO": "read_outgoing", "RI": "read_incoming", "RE": "read_edge", "RD": "read_dict", "RDN": "read_dict_node", "RDNE": "read_dict_node_edge", "RDE": "read_dict_edge", "RRD": "read_reverse_dict", "RR": "read_root", "RDK": "read_dict_keys", "DE": "delete_edge", "DN": "delete_node", }[operation] class MvSState(object): def __init__(self): self.queue = [] self.output = None self.mvs = MvS() self.timer = float("inf") class ModelverseState(AtomicDEVS): def __init__(self, read_root, create_node, create_edge, create_nodevalue, create_dict, read_value, read_outgoing, read_incoming, read_edge, read_dict, read_dict_keys, read_dict_edge, read_dict_node, read_dict_node_edge, read_reverse_dict, delete_node, delete_edge): AtomicDEVS.__init__(self, "MvS") self.timings = { "read_root": read_root, "create_node": create_node, "create_edge": create_edge, "create_nodevalue": create_nodevalue, "create_dict": create_dict, "read_value": read_value, "read_outgoing": read_outgoing, "read_incoming": read_incoming, "read_edge": read_edge, "read_dict": read_dict, "read_dict_keys": read_dict_keys, "read_dict_edge": read_dict_edge, "read_dict_node": read_dict_node, "read_dict_node_edge": read_dict_node_edge, "read_reverse_dict": read_reverse_dict, "delete_node": delete_node, "delete_edge": delete_edge, } self.from_mvk = self.addInPort("from_MvK") self.to_mvk = self.addOutPort("to_MvK") def extTransition(self, inputs): self.state.timer -= self.elapsed self.state.queue.extend(inputs[self.from_mvk]) return self.state def outputFnc(self): if self.state.output is not None: return {self.to_mvk: [self.state.output]} else: return {} def intTransition(self): self.state.output = None if self.state.queue: self.state.output = [] value = self.state.queue.pop(0) # Value contains a list of operations to do # So do them and calculate how long it took! for v in value: self.state.output.append(getattr(self.state.mvs, translate(v[0]))(*v[1])[0]) self.state.timer += self.timings[translate(v[0])] return self.state def timeAdvance(self): return self.state.timer class MvKState(object): def __init__(self): self.mvk = MvK() class ModelverseKernel(AtomicDEVS): def __init__(self): AtomicDEVS.__init__(self, "MvK") self.state = MvKState() self.from_mvi = self.addInPort("from_MvI") self.from_mvs = self.addInPort("from_MvS") self.to_mvi = self.addOutPort("to_MvI") self.to_mvs = self.addOutPort("to_MvS") def extTransition(self, inputs): if self.from_mvi in inputs: # Got input from MvI, so we queue it pass elif self.from_mvs in inputs: # Got input from MvS, so we can continue processing pass return self.state class MvIState(): def __init__(self): self.operations = [] self.output = [] self.memory = {} class ModelverseInterface(AtomicDEVS): def __init__(self, operations): AtomicDEVS.__init__(self, "MvI") self.state = MvIState() self.state.operations = operations self.to_mvk = self.addOutPort("to_MvK") self.from_mvk = self.addInPort("from_MvK") def intTransition(self): while self.state.operations: i = self.state.operations[0] if isinstance(i, int) and i not in self.memory: break self.state.operations.pop(0) return self.state def extTransition(self, inputs): for inp in inputs[self.from_mvk]: if inp["value"] == "None" and isinstance(self.state.processing[0], int) and self.state.processing[0] not in self.memory: self.state.memory[self.state.processing.pop(0)] = int(inp["id"]) else: self.state.output.append(inp) return self.state def outputFnc(self): send = [] for i in self.state.operations: if isinstance(i, int) and i not in self.memory: break elif isinstance(i, int) and i in self.memory: # Pass a reference! send.append(("R", self.memory[i])) elif not isinstance(i, int): send.append(("V", i)) return {self.to_mvk: [json.dumps(send)]} def timeAdvance(self): if self.state.processing and (not isinstance(self.state.processing[0], int) or self.state.processing[0] in self.memory): return 0 else: return float("inf") class NetworkState(object): def __init__(self): self.processing = [] self.timer = float("inf") class Network(AtomicDEVS): def __init__(self, latency, bytes_per_second): AtomicDEVS.__init__(self, "Network") self.state = NetworkState() self.input_port = self.addInPort("input_port") self.output_port = self.addOutPort("output_port") self.latency = latency self.bytes_per_second = bytes_per_second def intTransition(self): self.state.processing.pop(0) if self.state.processing: self.state.timer = len(self.state.processing[0]) / self.bytes_per_second + self.latency else: self.state.timer = float("inf") return self.state def extTransition(self, inputs): self.state.timer -= self.elapsed self.state.processing.extend(inputs[self.input_port]) return self.state def outputFnc(self): return {self.output_port: [self.state.processing[0]]} def timeAdvance(self): return self.state.timer class System(CoupledDEVS): def __init__(self, operations, mvi2mvk_latency, mvi2mvk_bandwidth, mvk2mvs_latency, mvk2mvs_bandwidth, mvs2mvk_latency, mvs2mvk_bandwidth, mvk2mvi_latency, mvk2mvi_bandwidth, read_root, create_node, create_edge, create_nodevalue, create_dict, read_value, read_outgoing, read_incoming, read_edge, read_dict, read_dict_keys, read_dict_edge, read_dict_node, read_dict_node_edge, read_reverse_dict, delete_node, delete_edge): CoupledDEVS.__init__(self, "System") self.mvi = self.addSubModel(ModelverseInterface(\ operations = operations )) self.mvk = self.addSubModel(ModelverseKernel()) self.mvs = self.addSubModel(ModelverseState(\ read_root = read_root, create_node = create_node, create_edge = create_edge, create_nodevalue = create_nodevalue, create_dict = create_dict, read_value = read_value, read_outgoing = read_outgoing, read_incoming = read_incoming, read_edge = read_edge, read_dict = read_dict, read_dict_keys = read_dict_keys, read_dict_edge = read_dict_edge, read_dict_node = read_dict_node, read_dict_node_edge = read_dict_node_edge, read_reverse_dict = read_reverse_dict, delete_node = delete_node, delete_edge = delete_edge )) self.mvi2mvk = self.addSubModel(Network(\ mvi2mvk_latency = mvi2mvk_latency, mvi2mvk_bandwidth = mvi2mvk_bandwidth )) self.mvk2mvs = self.addSubModel(Network(\ mvk2mvs_latency = mvk2mvs_latency, mvk2mvs_bandwidth = mvk2mvs_bandwidth )) self.mvs2mvk = self.addSubModel(Network(\ mvs2mvk_latency = mvs2mvk_latency, mvs2mvk_bandwidth = mvs2mvk_bandwidth )) self.mvk2mvi = self.addSubModel(Network(\ mvk2mvi_latency = mvk2mvi_latency, mvk2mvi_bandwidth = mvk2mvi_bandwidth )) self.connectPorts(self.mvi.to_mvk, self.mvi2mvk.input_port) self.connectPorts(self.mvi2mvk.output_port, self.mvk.from_mvi) self.connectPorts(self.mvk.to_mvs, self.mvk2mvs.input_port) self.connectPorts(self.mvk2mvs.output_port, self.mvs.from_mvk) self.connectPorts(self.mvs.to_mvk, self.mvs2mvk.input_port) self.connectPorts(self.mvs2mvk.output_port, self.mvk.from_mvs) self.connectPorts(self.mvk.to_mvi, self.mvk2mvi.input_port) self.connectPorts(self.mvk2mvi.output_port, self.mvi.from_mvk)