model.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. import sys
  2. import time
  3. import uuid
  4. sys.path.append("kernel/")
  5. sys.path.append("state/")
  6. sys.path.append("interface/HUTN")
  7. from modelverse_state.main import ModelverseState as MvS
  8. from modelverse_kernel.main import ModelverseKernel as MvK
  9. from modelverse_kernel.primitives import SleepKernel
  10. import modelverse_jit.jit as jit
  11. from hutn_compiler.compiler import main as do_compile
  12. from pypdevs.minimal import AtomicDEVS, CoupledDEVS, Simulator
  13. PROFILE = False
  14. import json
  15. import random
  16. random.seed(1)
  17. COMPILER_PATH = "interface/HUTN"
  18. sys.path.append(COMPILER_PATH)
  19. from hutn_compiler.compiler import main as do_compile
  20. import os
  21. def clean_code(code):
  22. if code == "":
  23. return code
  24. code_fragments = code.split("\n")
  25. code_fragments = [i.rstrip() for i in code_fragments if i.strip() != ""]
  26. code_fragments = [i.replace(" ", "\t") for i in code_fragments]
  27. initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
  28. code_fragments = [i[initial_tabs:] for i in code_fragments]
  29. code_fragments.append("")
  30. code = "\n".join(code_fragments)
  31. return code.encode('ascii', 'replace')
  32. def compile_model(temp_file):
  33. compiled = do_compile(temp_file, COMPILER_PATH + "/grammars/modelling.g", "M")
  34. return ["__LOCAL__"] + compiled
  35. trans_map = {
  36. "CN": "create_node",
  37. "CE": "create_edge",
  38. "CNV": "create_nodevalue",
  39. "CD": "create_dict",
  40. "RV": "read_value",
  41. "RO": "read_outgoing",
  42. "RI": "read_incoming",
  43. "RE": "read_edge",
  44. "RD": "read_dict",
  45. "RDN": "read_dict_node",
  46. "RDNE": "read_dict_node_edge",
  47. "RDE": "read_dict_edge",
  48. "RRD": "read_reverse_dict",
  49. "RR": "read_root",
  50. "RDK": "read_dict_keys",
  51. "DE": "delete_edge",
  52. "DN": "delete_node",
  53. "GC": "purge",
  54. }
  55. def translate(operation):
  56. return trans_map[operation]
  57. class MvSState(object):
  58. def __init__(self):
  59. self.queue = []
  60. self.output = None
  61. self.mvs = MvS("bootstrap/bootstrap.m.gz")
  62. self.timer = float("inf")
  63. class ModelverseState(AtomicDEVS):
  64. def __init__(self,
  65. read_root,
  66. create_node,
  67. create_edge,
  68. create_nodevalue,
  69. create_dict,
  70. read_value,
  71. read_outgoing,
  72. read_incoming,
  73. read_edge,
  74. read_dict,
  75. read_dict_keys,
  76. read_dict_edge,
  77. read_dict_node,
  78. read_dict_node_edge,
  79. read_reverse_dict,
  80. delete_node,
  81. delete_edge,
  82. purge):
  83. AtomicDEVS.__init__(self, "MvS")
  84. self.timings = {
  85. "read_root": read_root,
  86. "create_node": create_node,
  87. "create_edge": create_edge,
  88. "create_nodevalue": create_nodevalue,
  89. "create_dict": create_dict,
  90. "read_value": read_value,
  91. "read_outgoing": read_outgoing,
  92. "read_incoming": read_incoming,
  93. "read_edge": read_edge,
  94. "read_dict": read_dict,
  95. "read_dict_keys": read_dict_keys,
  96. "read_dict_edge": read_dict_edge,
  97. "read_dict_node": read_dict_node,
  98. "read_dict_node_edge": read_dict_node_edge,
  99. "read_reverse_dict": read_reverse_dict,
  100. "delete_node": delete_node,
  101. "delete_edge": delete_edge,
  102. "purge": purge,
  103. }
  104. self.state = MvSState()
  105. self.from_mvk = self.addInPort("from_MvK")
  106. self.to_mvk = self.addOutPort("to_MvK")
  107. def extTransition(self, inputs):
  108. self.state.timer -= self.elapsed
  109. empty = len(self.state.queue) == 0
  110. self.state.queue.extend(inputs[self.from_mvk])
  111. if empty:
  112. # First message, so set the timer
  113. # And already compute the result so it is ready to output
  114. self.state.output = []
  115. self.state.timer = 0.0
  116. for v in self.state.queue[0]:
  117. f = getattr(self.state.mvs, translate(v[0]))
  118. start = time.time()
  119. self.state.output.append(f(*v[1]))
  120. if PROFILE:
  121. print("%s: %.17f" % (translate(v[0]), time.time() - start))
  122. self.state.timer += self.timings[translate(v[0])]
  123. else:
  124. # Just append the message to process
  125. pass
  126. return self.state
  127. def outputFnc(self):
  128. return {self.to_mvk: [self.state.output]}
  129. def intTransition(self):
  130. self.state.queue.pop(0)
  131. self.state.output = []
  132. if len(self.state.queue) > 0:
  133. self.state.timer = 0.0
  134. # Value contains a list of operations to do
  135. # So do them and calculate how long it takes
  136. for v in self.state.queue[0]:
  137. f = getattr(self.state.mvs, translate(v[0]))
  138. start = time.time()
  139. self.state.output.append(f(*v[1]))
  140. if PROFILE:
  141. print("%s: %.17f" % (translate(v[0]), time.time() - start))
  142. self.state.timer += self.timings[translate(v[0])]
  143. else:
  144. self.state.timer = float("inf")
  145. return self.state
  146. def timeAdvance(self):
  147. return self.state.timer
  148. class MvKState(object):
  149. def __init__(self, rule_generation):
  150. self.mvk = None
  151. self.waiting = False
  152. self.inputs = {}
  153. self.outputs = {}
  154. self.tasks = []
  155. self.reply = None
  156. self.phase = None
  157. self.commands = None
  158. self.root = None
  159. self.current_task = None
  160. self.loaded_primitives = False
  161. self.execution_counter = 0
  162. self.rule_generation = rule_generation
  163. self.current_time = 0.0
  164. self.start_task_time = 0.0
  165. self.execution_rounds = 0
  166. def __str__(self):
  167. return "\nMvK: %s\n" % self.mvk + \
  168. "waiting: %s\n" % self.waiting + \
  169. "inputs: %s\n" % self.inputs + \
  170. "outputs: %s\n" % self.outputs + \
  171. "tasks: %s\n" % self.tasks + \
  172. "reply: %s\n" % self.reply + \
  173. "phase: %s\n" % self.phase + \
  174. "commands: %s\n" % self.commands + \
  175. "root: %s\n" % self.root + \
  176. "current task: %s\n" % self.current_task + \
  177. "execution counter: %s\n"
  178. class ModelverseKernel(AtomicDEVS):
  179. def __init__(self, time_per_phase, rule_generation):
  180. AtomicDEVS.__init__(self, "MvK")
  181. self.state = MvKState(rule_generation)
  182. self.from_mvi = self.addInPort("from_MvI")
  183. self.from_mvs = self.addInPort("from_MvS")
  184. self.to_mvi = self.addOutPort("to_MvI")
  185. self.to_mvs = self.addOutPort("to_MvS")
  186. self.time_per_phase = time_per_phase
  187. def extTransition(self, inputs):
  188. self.state.current_time += self.elapsed
  189. if self.from_mvi in inputs:
  190. # Got input from MvI, so we queue it
  191. for inp in inputs[self.from_mvi]:
  192. taskname = inp[0]
  193. data = inp[1]
  194. if data is not None:
  195. self.state.inputs.setdefault(taskname, []).extend(data)
  196. else:
  197. self.state.outputs.setdefault(taskname, []).append(None)
  198. if self.from_mvs in inputs:
  199. # Got input from MvS, so we can continue processing
  200. for mvs_input in inputs[self.from_mvs]:
  201. if self.state.mvk is None:
  202. # No MvK, so set it with the root we have just received (or should have received)
  203. self.state.root = mvs_input[0]
  204. self.state.mvk = MvK(self.state.root)
  205. self.state.mvk.jit.set_function_body_compiler(jit.compile_function_body_fast)
  206. else:
  207. self.state.reply = mvs_input
  208. self.state.waiting = False
  209. return self.state
  210. def intTransition(self):
  211. self.state.current_time += self.timeAdvance()
  212. was_empty = len(self.state.tasks) == 0
  213. if self.state.commands is not None:
  214. self.state.commands = None
  215. return self.state
  216. if self.state.mvk is not None:
  217. self.state.mvk.returnvalue = None
  218. if self.state.mvk is None:
  219. # Initializing
  220. self.state.waiting = True
  221. elif not self.state.loaded_primitives:
  222. commands = self.state.mvk.execute_yields("", "load_primitives", [], self.state.reply)
  223. if commands is None:
  224. self.state.loaded_primitives = True
  225. self.state.reply = None
  226. else:
  227. self.state.waiting = True
  228. self.state.commands = commands
  229. else:
  230. # Are initialized and have work to do
  231. if len(self.state.tasks) == 0:
  232. # Read out new set of tasks first
  233. if self.state.reply is None:
  234. self.state.execution_rounds += 1
  235. commands = [("RDK", [self.state.root])]
  236. if self.state.execution_rounds > 1000:
  237. commands.append(("GC", []))
  238. self.state.execution_rounds = 0
  239. else:
  240. self.state.tasks = self.state.reply[0]
  241. commands = None
  242. elif self.state.phase == "init_task":
  243. if self.state.reply is None:
  244. commands = [("RV", [self.state.tasks[0]])]
  245. else:
  246. self.state.current_task = self.state.reply[0]
  247. self.state.start_task_time = self.state.current_time
  248. if self.state.current_task.startswith("__"):
  249. # Don't process this task and force termination of task
  250. self.state.phase = "output"
  251. commands = None
  252. elif self.state.phase == "input":
  253. # Process inputs
  254. if self.state.inputs.get(self.state.current_task, None):
  255. value = self.state.inputs[self.state.current_task][0]
  256. start = time.time()
  257. commands = self.state.mvk.execute_yields(self.state.current_task, "set_input", [value], self.state.reply)
  258. #print("EXECUTEYIELDSI %s %.17f" % (self.state.current_task, time.time() - start))
  259. #print(commands)
  260. if PROFILE:
  261. print("rule_generation: %.17f" % ((time.time() - start)))
  262. #self.state.rule_generation = time.time() - start
  263. self.state.mvk.returnvalue = None
  264. if commands is None:
  265. self.state.inputs[self.state.current_task].pop(0)
  266. else:
  267. commands = None
  268. elif self.state.phase == "computation":
  269. try:
  270. start = time.time()
  271. commands = self.state.mvk.execute_yields(self.state.current_task, "execute_rule", [], self.state.reply)
  272. #print("EXECUTEYIELDS %s %.17f" % (self.state.current_task, time.time() - start))
  273. #print(commands)
  274. if PROFILE:
  275. print("rule_generation: %.17f" % ((time.time() - start)))
  276. except SleepKernel:
  277. commands = None
  278. self.state.mvk.success = False
  279. else:
  280. self.state.mvk.success = True
  281. elif self.state.phase == "output":
  282. start = time.time()
  283. commands = self.state.mvk.execute_yields(self.state.current_task, "get_output", [], self.state.reply)
  284. #print("EXECUTEYIELDSO %s %.17f" % (self.state.current_task, time.time() - start))
  285. #print(commands)
  286. if PROFILE:
  287. print("rule_generation: %.17f" % ((time.time() - start)))
  288. #self.state.rule_generation = time.time() - start
  289. else:
  290. raise Exception("Phase: " + str(self.state.phase))
  291. # Advance phase
  292. if commands is None:
  293. if was_empty:
  294. self.state.phase = "init_task"
  295. elif self.state.phase == "init_task":
  296. self.state.phase = "input"
  297. elif self.state.phase == "input":
  298. self.state.phase = "computation"
  299. elif self.state.phase == "computation":
  300. if (not self.state.mvk.success) or (self.state.current_time - self.state.start_task_time > self.time_per_phase):
  301. self.state.phase = "output"
  302. elif self.state.phase == "output":
  303. self.state.tasks.pop(0)
  304. self.state.phase = "init_task"
  305. self.state.waiting = False
  306. self.state.reply = None
  307. else:
  308. self.state.waiting = True
  309. # Send the commands to the MvS
  310. self.state.commands = commands
  311. return self.state
  312. def outputFnc(self):
  313. outputs = {}
  314. if self.state.mvk is None:
  315. # Ask the root first
  316. outputs[self.to_mvs] = [[("RR", [])]]
  317. elif self.state.waiting:
  318. outputs[self.to_mvs] = [self.state.commands]
  319. if self.state.mvk and self.state.mvk.returnvalue is not None:
  320. outputs[self.to_mvi] = [(self.state.current_task, self.state.mvk.returnvalue)]
  321. return outputs
  322. def timeAdvance(self):
  323. if self.state.commands is not None:
  324. return self.state.rule_generation
  325. elif self.state.waiting:
  326. return float("inf")
  327. elif self.state.mvk is None:
  328. return 0
  329. else:
  330. return 0
  331. class MvIState():
  332. def __init__(self):
  333. self.operations = []
  334. self.additional_operations = []
  335. self.keyed_operations = {}
  336. self.task_to_spawner = {}
  337. self.task_to_operation = {}
  338. self.output = {}
  339. self.blocked = True
  340. self.finished = False
  341. self.send_operations = {}
  342. class ModelverseInterface(AtomicDEVS):
  343. def __init__(self, taskname, operations, finish_on, additional_operations=[], keyed_operations={}):
  344. AtomicDEVS.__init__(self, "MvI_%s" % taskname)
  345. self.state = MvIState()
  346. if taskname == "task_manager":
  347. self.state.blocked = False
  348. self.state.operations = operations
  349. self.state.additional_operations = additional_operations
  350. self.state.keyed_operations = keyed_operations
  351. self.state.create_additional_task = []
  352. self.taskname = taskname
  353. self.finish_on = finish_on
  354. self.to_mvk = self.addOutPort("to_MvK")
  355. self.from_mvk = self.addInPort("from_MvK")
  356. def intTransition(self):
  357. self.state.create_additional_task = []
  358. if not self.state.send_operations:
  359. self.state.operations.pop(0)
  360. else:
  361. for k in self.state.send_operations.keys():
  362. if self.state.send_operations[k]:
  363. self.state.send_operations[k][0] = None
  364. self.state.blocked = True
  365. return self.state
  366. def extTransition(self, inputs):
  367. for inp in inputs[self.from_mvk]:
  368. #print(inp)
  369. self.state.blocked = False
  370. self.state.output.setdefault(inp[0], []).append(inp[1])
  371. if inp[0] == self.taskname and inp[1] == self.finish_on:
  372. self.state.finished = True
  373. elif inp[0] == self.taskname and self.state.operations[0] is None:
  374. # We have to block for now, and modify a model first...
  375. prev_output = self.state.output[inp[0]][-1]
  376. if prev_output.startswith("Please edit this model before sending next input: "):
  377. _, model_name = prev_output.split("Please edit this model before sending next input: ", 1)
  378. new_taskname = str(uuid.uuid4())
  379. self.state.send_operations[new_taskname] = [[], ["admin"], ["admin"], ["quiet"], ["model_modify", model_name, ""]] + self.state.additional_operations[0] + [["exit"], ["exit"]]
  380. self.state.create_additional_task.append(new_taskname)
  381. self.state.task_to_operation[new_taskname] = None
  382. self.state.task_to_spawner[new_taskname] = None
  383. elif prev_output.startswith("Spawned activity on task: "):
  384. _, task_name = prev_output.split("Spawned activity on task: ", 1)
  385. self.state.blocked = True
  386. self.state.task_to_spawner[task_name] = None
  387. # NOTE We now know that there is something to do on an other task, so we just wait for that event to come in
  388. self.state.operations.insert(0, None)
  389. self.state.operations.insert(0, None)
  390. elif prev_output.startswith("Finished task: "):
  391. self.state.blocked = True
  392. elif " : " in prev_output:
  393. task_name, _ = prev_output.split(" : ", 1)
  394. self.state.blocked = True
  395. self.state.task_to_spawner[task_name] = None
  396. # NOTE We now know that there is something to do on an other task, so we just wait for that event to come in
  397. self.state.operations.insert(0, None)
  398. self.state.operations.insert(0, None)
  399. elif prev_output == "Success":
  400. self.state.operations.pop(0)
  401. self.state.blocked = False
  402. elif inp[0] != self.taskname:
  403. # Got some output on another task
  404. # If the task is not registered yet, it is likely not important to communicate with it, so ignore it
  405. #print("Send operations: " + str(self.state.send_operations))
  406. if inp[0] in self.state.send_operations:
  407. self.state.send_operations[inp[0]].pop(0)
  408. if inp[1].startswith("Please edit this model before sending next input: "):
  409. _, model_name = inp[1].split("Please edit this model before sending next input: ", 1)
  410. new_taskname = str(uuid.uuid4())
  411. self.state.send_operations[new_taskname] = [[], ["admin"], ["admin"], ["quiet"], ["model_modify", model_name, ""]] + self.state.keyed_operations.get(self.state.task_to_operation[inp[0]], []) + [["exit"], ["exit"]]
  412. #print("DO EXIT2")
  413. self.state.create_additional_task.append(new_taskname)
  414. self.state.task_to_spawner[new_taskname] = inp[0]
  415. elif inp[1].startswith("Please perform manual operation "):
  416. _, op_name = inp[1].split("Please perform manual operation ", 1)
  417. self.state.task_to_operation[inp[0]] = op_name[1:-1]
  418. if inp[0] in self.state.send_operations and len(self.state.send_operations[inp[0]]) == 0:
  419. del self.state.send_operations[inp[0]]
  420. # At the end of these operations, so finish up!
  421. if inp[0] in self.state.task_to_spawner:
  422. if self.state.task_to_spawner[inp[0]] is not None:
  423. self.state.keyed_operations.pop(self.state.task_to_operation[self.state.task_to_spawner[inp[0]]], None)
  424. self.state.additional_operations.insert(0, [])
  425. self.state.send_operations[self.state.task_to_spawner[inp[0]]] = ["__continue__"]
  426. else:
  427. self.state.additional_operations.pop(0)
  428. self.state.operations.pop(0)
  429. return self.state
  430. def outputFnc(self):
  431. if self.state.send_operations:
  432. outp = []
  433. if self.state.create_additional_task:
  434. outp.append(('task_manager', self.state.create_additional_task))
  435. for k, v in self.state.send_operations.items():
  436. if v and v[0] is not None:
  437. outp.append((k, v[0]))
  438. if outp:
  439. #print("SEND " + str(outp))
  440. return {self.to_mvk: outp}
  441. else:
  442. return {}
  443. elif self.state.operations and self.state.operations[0] is not None:
  444. #print("SEND " + str([(self.taskname, self.state.operations[0])]))
  445. return {self.to_mvk: [(self.taskname, self.state.operations[0])]}
  446. else:
  447. return {}
  448. def timeAdvance(self):
  449. if self.state.blocked:
  450. return float("inf")
  451. else:
  452. return 0.0
  453. class NetworkState(object):
  454. def __init__(self):
  455. self.processing = []
  456. self.timer = float("inf")
  457. class Network(AtomicDEVS):
  458. def __init__(self, name, latency, bandwidth):
  459. AtomicDEVS.__init__(self, name)
  460. self.state = NetworkState()
  461. self.input_port = self.addInPort("input_port")
  462. self.output_port = self.addOutPort("output_port")
  463. self.latency = latency
  464. self.bandwidth = bandwidth
  465. def intTransition(self):
  466. self.state.processing.pop(0)
  467. if self.state.processing:
  468. self.state.timer = (len(json.dumps(self.state.processing[0])) * 8 / float(self.bandwidth) + self.latency)
  469. else:
  470. self.state.timer = float("inf")
  471. return self.state
  472. def extTransition(self, inputs):
  473. self.state.timer -= self.elapsed
  474. if self.state.timer == float("inf"):
  475. self.state.timer = 0
  476. for v in inputs[self.input_port]:
  477. self.state.processing.append(v)
  478. # NOTE data is in bytes, while bandwidth is in bits, so multiply by 8
  479. if len(self.state.processing) > 0:
  480. self.state.timer = (len(json.dumps(self.state.processing[0])) * 8 / float(self.bandwidth) + self.latency)
  481. return self.state
  482. def outputFnc(self):
  483. return {self.output_port: [self.state.processing[0]]}
  484. def timeAdvance(self):
  485. return self.state.timer
  486. class System(CoupledDEVS):
  487. def __init__(self,
  488. taskname,
  489. operations,
  490. mvi_additional,
  491. mvi_keyed,
  492. finish_on,
  493. rule_generation,
  494. time_per_phase,
  495. mvi2mvk_latency,
  496. mvi2mvk_bandwidth,
  497. mvk2mvs_latency,
  498. mvk2mvs_bandwidth,
  499. mvs2mvk_latency,
  500. mvs2mvk_bandwidth,
  501. mvk2mvi_latency,
  502. mvk2mvi_bandwidth,
  503. read_root,
  504. create_node,
  505. create_edge,
  506. create_nodevalue,
  507. create_dict,
  508. read_value,
  509. read_outgoing,
  510. read_incoming,
  511. read_edge,
  512. read_dict,
  513. read_dict_keys,
  514. read_dict_edge,
  515. read_dict_node,
  516. read_dict_node_edge,
  517. read_reverse_dict,
  518. delete_node,
  519. delete_edge,
  520. purge):
  521. CoupledDEVS.__init__(self, "System")
  522. self.mvi_manager = self.addSubModel(ModelverseInterface(\
  523. taskname = "task_manager",
  524. operations = [[taskname]],
  525. finish_on = None,
  526. ))
  527. self.mvi = self.addSubModel(ModelverseInterface(\
  528. taskname = taskname,
  529. operations = operations,
  530. finish_on = finish_on,
  531. additional_operations = mvi_additional,
  532. keyed_operations = mvi_keyed,
  533. ))
  534. self.mvk = self.addSubModel(ModelverseKernel(\
  535. time_per_phase = time_per_phase,
  536. rule_generation = rule_generation,
  537. ))
  538. self.mvs = self.addSubModel(ModelverseState(\
  539. read_root = read_root,
  540. create_node = create_node,
  541. create_edge = create_edge,
  542. create_nodevalue = create_nodevalue,
  543. create_dict = create_dict,
  544. read_value = read_value,
  545. read_outgoing = read_outgoing,
  546. read_incoming = read_incoming,
  547. read_edge = read_edge,
  548. read_dict = read_dict,
  549. read_dict_keys = read_dict_keys,
  550. read_dict_edge = read_dict_edge,
  551. read_dict_node = read_dict_node,
  552. read_dict_node_edge = read_dict_node_edge,
  553. read_reverse_dict = read_reverse_dict,
  554. delete_node = delete_node,
  555. delete_edge = delete_edge,
  556. purge = purge,
  557. ))
  558. self.mvi2mvk = self.addSubModel(Network(\
  559. name = "mvi2mvk",
  560. latency = mvi2mvk_latency,
  561. bandwidth = mvi2mvk_bandwidth,
  562. ))
  563. self.mvk2mvs = self.addSubModel(Network(\
  564. name = "mvk2mvs",
  565. latency = mvk2mvs_latency,
  566. bandwidth = mvk2mvs_bandwidth,
  567. ))
  568. self.mvs2mvk = self.addSubModel(Network(\
  569. name = "mvs2mvk",
  570. latency = mvs2mvk_latency,
  571. bandwidth = mvs2mvk_bandwidth,
  572. ))
  573. self.mvk2mvi = self.addSubModel(Network(\
  574. name = "mvk2mvi",
  575. latency = mvk2mvi_latency,
  576. bandwidth = mvk2mvi_bandwidth,
  577. ))
  578. self.connectPorts(self.mvi_manager.to_mvk, self.mvk.from_mvi)
  579. self.connectPorts(self.mvi.to_mvk, self.mvi2mvk.input_port)
  580. self.connectPorts(self.mvi2mvk.output_port, self.mvk.from_mvi)
  581. self.connectPorts(self.mvk.to_mvs, self.mvk2mvs.input_port)
  582. self.connectPorts(self.mvk2mvs.output_port, self.mvs.from_mvk)
  583. self.connectPorts(self.mvs.to_mvk, self.mvs2mvk.input_port)
  584. self.connectPorts(self.mvs2mvk.output_port, self.mvk.from_mvs)
  585. self.connectPorts(self.mvk.to_mvi, self.mvk2mvi.input_port)
  586. self.connectPorts(self.mvk2mvi.output_port, self.mvi.from_mvk)
  587. taskname = "test_task"
  588. operations = json.loads(open("model/operations", 'r').read())
  589. #operations = json.loads(open("model/operations_simple", 'r').read())
  590. additional_operations = [[], # revise_req
  591. [], # revise_environment
  592. [], # revise_plant
  593. [], # revise_control
  594. [], # revise_query
  595. [], # revise_architecture
  596. [], # make_initial_models
  597. [["instantiate_edge", "Association", "PLANT2EPN_link", "PW_Plant/State", "Encapsulated_PetriNet/Place"], ["instantiate_edge", "Association", "PLANT2EPN_tlink", "PW_Plant/Transition", "Encapsulated_PetriNet/Transition"]], # plant_to_EPN
  598. [["instantiate_edge", "Association", "CTRL2EPN_link", "PW_Control/State", "Encapsulated_PetriNet/Place"], ["instantiate_edge", "Association", "CTRL2EPN_tlink", "PW_Control/Transition", "Encapsulated_PetriNet/Transition"]], # control_to_EPN
  599. [["instantiate_edge", "Association", "ENV2EPN_link", "PW_Environment/Event", "Encapsulated_PetriNet/Place"]], # environment_to_EPN
  600. [["instantiate_edge", "Association", "EPN2PN_place_link", "Encapsulated_PetriNet/Place", "PetriNet/Place"], ["instantiate_edge", "Association", "EPN2PN_transition_link", "Encapsulated_PetriNet/Transition", "PetriNet/Transition"]], # EPN_to_PN
  601. [], # match
  602. [], # reachability
  603. [], # bfs
  604. [], # merge
  605. ]
  606. #additional_operations = [[]]
  607. keyed_operations = {"models/revise_req": [["upload"], compile_model("models/requirements_model.mvc")],
  608. "models/revise_plant": [["upload"], compile_model("models/plant_model.mvc")],
  609. "models/revise_environment": [["upload"], compile_model("models/environment_model.mvc")],
  610. "models/revise_control": [["upload"], compile_model("models/control_model.mvc")],
  611. "models/revise_query": [["upload"], compile_model("models/query_model.mvc")],
  612. "models/revise_architecture": [["upload"], compile_model("models/architecture_model.mvc")],
  613. }
  614. #keyed_operations = {"models/modify_lang": [["instantiate_node", "PN/Class", ""]]}
  615. finish_on = "FINISHED"
  616. args = {
  617. "taskname": taskname,
  618. "operations": operations,
  619. "finish_on": finish_on,
  620. "mvi_additional": additional_operations,
  621. "mvi_keyed": keyed_operations,
  622. "mvi2mvk_latency": 0.0000001,
  623. "mvi2mvk_bandwidth": 50000000000,
  624. "mvk2mvs_latency": 0.0000001,
  625. "mvk2mvs_bandwidth": 50000000000,
  626. "mvs2mvk_latency": 0.0000001,
  627. "mvs2mvk_bandwidth": 50000000000,
  628. "mvk2mvi_latency": 0.0000001,
  629. "mvk2mvi_bandwidth": 50000000000,
  630. "time_per_phase": 0.05,
  631. # Automatically filled in from calibration results, just here to prevent crashes (results for my UA desktop)
  632. "read_root": 0.00001406669616699,
  633. "create_node": 0.00000379181167487,
  634. "create_edge": 0.00000601282282066,
  635. "create_nodevalue": 0.00000501364247391,
  636. "create_dict": 0.00001028065706205,
  637. "read_value": 0.00000388661630500,
  638. "read_outgoing": 0.00000520600098073,
  639. "read_incoming": 0.00000645903181994,
  640. "read_edge": 0.00000449162172644,
  641. "read_dict": 0.00000460127038355,
  642. "read_dict_keys": 0.00001678063432883,
  643. "read_dict_node": 0.00001020808859528,
  644. "read_dict_edge": 0.00000642558526942,
  645. "read_dict_node_edge": 0.0,
  646. "read_reverse_dict": 0.00002557890755790,
  647. "delete_node": 0.00004755891187096,
  648. "delete_edge": 0.00000683382081240,
  649. "rule_generation": 0.00001543215873893,
  650. "purge": 7.0,
  651. }
  652. with open("calibration/averages", 'r') as param_file:
  653. for l in param_file:
  654. op, t = l.split(": ")
  655. op = op.strip()
  656. args[op] = float(t)
  657. model = System(**args)
  658. sim = Simulator(model)
  659. sim.setTerminationCondition(lambda t, m: m.mvi.state.finished)
  660. #sim.setVerbose()
  661. start = time.time()
  662. tn = sim.simulate()
  663. print("Simulation time %s" % tn)
  664. print("Execution time %s" % (time.time() - start))